Страницы: Пред. 1 2 3 След.
RSS
Восстановление связи с Ribbon
 
Цитата
Ткач Александр написал: данные о системе
Александр, спасибо, записал номер версии. Удалите , пожалуйста, 2-ю картинку с кодом продукта.
 
См. ниже
Изменено: ZVI - 17.10.2019 17:53:41
 
Цитата
Ткач Александр написал: Высылаю ссылку на файл
Спасибо, достаточно было пустого файла с проблемным кодом.
Вставил в модуль API_function вместо строки с RtlMoveMemory такой код:
Код
#If VBA7 Then
  Public Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByRef destination As Any, ByRef Source As Any, ByVal length As LongPtr)
#Else
  Public Declare Sub RtlMoveMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef destination As Any, ByRef Source As Any, ByVal length As Long)
#End If

Компилируется без проблем, строка после #Else помечена красным и это нормальное описанное в документации поведение VBA,  означающее, что данный фрагмент в 64-битной версии не используется.
Проверьте, пожалуйста, у Вас с этим файлом при подобной замене кода выводится сообщение об ошибке при  VBE - Debug - Compile VBAProject ?
Изменено: ZVI - 17.10.2019 17:54:51
 
Цитата
ZVI написал:
Удалите , пожалуйста, 2-ю картинку с кодом продукта.
Владимир, добрый день. Это не ключ. Страшного ничего нет.
По вопросам из тем форума, личку не читаю.
 
Михаил, спасибо за уточнение  :)
 
Ткач Александр, я привел сравнение с плюсами не для того чтобы выделить какой либо язык, а наоборот, сказать о том, что для каждого языка есть своя ниша, где он хорошо справляется. Наверное теория Дарвина работает и здесь, раз жив, значит востребован. Ведь не поспоришь... Вот вы на Шарп какой функционал перевели? В какой форме: надстройка VSTO, Excel-DNA, СОМ-библиотека или обычная процедурная? А ведь еще есть возможности написать решения для Excel на (VBA - уже знаем, вам не подходит :) ), C/C++, JavaScript (коллеги дополните, если что упустил). Провокационный вопрос, какой из них лучший, и почему именно он?
Собственно заканчиваю: ИМХО, лучшего нет.
Да и конечно Владимир прав, обсуждение багов VBA - лучше в отдельную тему, не делать кашу здесь.
К сожалению, сейчас не могу протестировать решение предложенное Владимиром, но за темой слежу.
«Бритва Оккама» или «Принцип Калашникова»?
 
Добрый день коллеги!
Я поддерживаю предложение о том, что в данной теме должно быть обсуждение именно ее. Поэтому давайте закончим с багами, если кто-то хочет может открыть эту тему, я присоединюсь и буду выкладывать туда материалы. Поймите правильно, у меня крайне мало времени, я часто езжу в командировки (вчера писал из Москвы, сегодня из Тулы), вести тему форума я не смогу физически.
ZVI, спасибо, что вы внимательно отнеслись к моей проблеме, я теперь точно знаю, что у меня не бетта версия (я не проверяю, доверяя нашему сис админу)
Дело не только в том, что строка красная. Я использую процедуры перезаписи кода из кода во время исполнения с перекомпиляцией, и в этом случае перекомпиляция не выполняется. И этого вполне достаточно, чтобы не использовать такой подход. Еще учтите тот факт, что в файле может быть не 8-10 API (как в выложенном файле, который находится в начале разработки), а 30-40 штук. Теперь представьте себе массив объявлений самих API, и массив переменных типа LongPtr в различных модулях в разных частях проекта.
bedvit, мы с вами говорим на одном языке, и я поддерживаю, что
Цитата
что для каждого языка есть своя ниша, где он хорошо справляется
поэтому не вижу смысла поддюдюривать друг друга  :D . Я тщательно проверю подключение библиотек в Excel (как будет время), а потом поделюсь результатами.
Давайте все-таки вернемся к теме RibbonFluent, а то мы зашли совсем в другую сторону, заблудились можно сказать)))
 
Продолжая тему Johny, я бы не стал использовать именованный диапазон для записи ссылки на объект ленты IRibbonUI, а воспользовался более надежным местом - DocumentProperty (ссылка на DocumentProperty: https://docs.microsoft.com/ru-ru/office/vba/api/office.documentproperties.add ). Для этого несколько оснований:
  1. одна и таже ячейка может входить в несколько именованных диапазонов. Поэтому при  групповых операциях можно ненароком удалить как сам диапазон, так и очистить значения. К коллекции DocumentPropertys обращаются реже, если вообще обращаются.
  2. меньше преобразований текстовых строк , т.к. не нужно из формулы "=123456..." удалять знак равно.
Тогда модули будут выглядеть так:
Код
Public objRib as IRibbonUI 

'Загрузочная запись ленты Ribbon
Sub Ribbon_OnLoad(ribbon As IRibbonUI)

    Set objRib = ribbon

    'Записываем IRibbonUI в пользовательское свойство RibbonPointer
    Call WriteRibbon(objRib)

End Sub


'Обновление состояния элементов управления на Ленте.
'Обработка ошибок нужна, если по какой-то причине id objRib не сохранится
Sub RefreshRibbon()
On Error GoTo Err_discr
    
    'Проверяем переменную objRib объекта IRibbonUI текущего проекта.
    If objRib Is Nothing Then
        'Если переменная пустая, пытаемся восстановить objRib
        Call RestoreRibbon(objRib)
        'Если восстановление не получилось, выводим сообщение Err_discr
        If objRib Is Nothing Then _
            GoTo Err_discr
    End If
    
    'обновляем состояние элементов Ленты
    objRib.Invalidate

Exit Sub

Err_discr:
    MsgBox "Ошибка при обращении к Ленте." & _
            vbNewLine & "Сохраните и перезагрузите файл", _
                                        vbCritical, "ошибки ленты"

End Sub

'Процедура создает id ссылку на объект objRibbon типа IRibbonUI,
'в пользовательских свойствах DocumentProperties с именем "RibbonPointer".
'Если такого свойства нет, то создает его.
Sub WriteRibbon(objRibbon As Object)
    Dim pr As DocumentProperty 'пользовательское свойство
    Dim prs As DocumentProperties 'коллекция пользовательских свойств
    Dim bExist As Boolean
    
    'Проверяем пользовательские свойства проекта.
    Set prs = ThisWorkbook.CustomDocumentProperties
    'Ищем существует ли свойство RibbonPointer.
    bExist = False
    
    For Each pr In prs
        'Если свойство существует, устанавливаем переменную bExist=True,
        'и выходим из цикла
        If pr.Name = "RibbonPointer" Then _
            bExist = True: _
            Exit For
    Next
    
    'Если свойство не существует, добавляем его в коллекцию DocumentProperties.
    'Т.к. тип данных DocumentProperty не поддерживает LongPtr (LongLong),
    'записываем id объекта objRib в строку, с последующим преобразованием CLongPtr.
    'Поэтому используем тип данных msoPropertyTypeString, а не msoPropertyTypeNumber
    If Not bExist Then
        prs.Add "RibbonPointer", False, msoPropertyTypeString, ObjPtr(objRib)
    Else
       ThisWorkbook.CustomDocumentProperties("RibbonPointer").Value = ObjPtr(objRib)
    End If


End Sub

'Восстанавливает объект IRibbonUI из RibbonPointer
Sub RestoreRibbon(objRibbon As Object)
    Dim llPointer As LongPtr
    
    'Считываем ссылку на id objRib из свойства RibbonPointer.
    'Преобразуем значение RibbonPointer из строки в число.
    llPointer = CLngPtr(ThisWorkbook.CustomDocumentProperties("RibbonPointer"))
    
    'Перемещаем ссылку llPointer в объект objRib с помощью API процедуры RtlMoveMemory
    Call RtlMoveMemory(objRibbon, llPointer, LenB(llPointer))
 
End Sub
Я постарался подробнее закомментировать)
Изменено: Ткач Александр - 02.02.2020 18:14:37 (дополнено)
 
Цитата
Ткач Александр написал: ... я бы не стал использовать именованный диапазон для записи ссылки на объект ленты IRibbonUI,
Александр, в варианте Автора темы не используется именованный диапазон, использукется имя без привязки к ячейкам, это имя легко сделать невидимым, если что. Поэтому недостатка по п.1 нет.  А замечание по п.2  - на любителя, можно было и Evaluate использовать, да и избавление от "=" код не перегружает, зато нет цикла, например (есть здесь их нелюбители , не я) :)
Изменено: ZVI - 18.10.2019 20:26:00
 
Цитата
Ткач Александр написал:
поэтому не вижу смысла поддюдюривать друг друга
Не имею такой привычки, интересно чисто с профессиональной позиции, что удалось перевести с VBA на С#.NET, как это взаимодействует с VBA, Excel.
Цитата
Ткач Александр написал:
Дело не только в том, что строка красная. Я использую процедуры перезаписи кода из кода во время исполнения с перекомпиляцией, и в этом случае перекомпиляция не выполняется.
Не использовал никогда такие конструкции, для чего они, какой функционал несут?
По теме, за вариант кода плюсую и согласен с Владимиром, на любителя, но возможно кто-то будет использовать именно ваш.
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
despot69 написал: вы получите формулу "=33333333",
Код
Pointer = CLng([RibbonPointer]) =CLng("=33333333")
что приводит к ошибке.
Как-то мы увлеклись интересными высказываниями, но в цитате выше утверждение неверное.
У Автора темы все правильно: [RibbonPointer] = Evaluate("RibbonPointer") и выдает требуемое число, так как RibbonPointer это не переменная, а имя.
 
Добрый день, уважаемые коллеги!
ZVI, у автора темы п. 4, строки кода 6, 9
Код
lPointer = CLng([RibbonPointer])
И где вы видели Evaluate? Запись [...] лично у меня выдает ошибку, хотя должно работать. Но если бы и работало то мы получаем цепочку обработки данных Eval() => CLngPtr(), зачем? Мы же стремимся писать оптимально или не так?  К примеру, об операторе Mod тоже много написано.  Однако результат его применения в VBA не тот, который описан в VB. И еще раз обращу внимание, что я часто использую очистку Names, потому что диапазоны могут изменяться. Представьте 6 листов на каждом до 12-15 именованных диапазонов. Если я их буду перебирать поштучно по именам, то пользователь заснет, а код распухнет до небес. Поэтому я удаляю на каждой странице все, а затем заново переопределяю. А пользовательские свойства документа - гораздо более надежное хранилище в этом плане. И важную информацию лучше сохранять именно там, особенно касаемо инфы для единственного объекта в единственном экземпляре..
bedvit, если действительно интересно, то мы использовали следующий подход. Книга Excel - user interface, строки и колонки - поля данных, и просто разметка листа типа координатной сетки.
Наша надстройка на C# уровня файла (не приложения!). Каждый файл заточен под определенные данные. Например, в одном Организация корпоративов, в другом Анализ проектов предевелопмента и т.д. Данные хранятся в базе. При открытии файла данные подгружаются автоматом. В файле Excel работает user, там вычисления, графики и любые персональные данные и заметки. При закрытии файла  определенные данные подготавливаются и отправляются на сервер. Индивидуальная пользовательская информация сохраняется только в файле. Писано сразу на С# в VS и встроено в файл в виде надстройки средствами VS. VBA используется для макетирования, т.к позволяет выиграть время. Кроме того, если использовать один файл в процессе разработки, а затем писать надстройку, то там остается куча мусора, который без доступа к коду MSO убрать практически невозможно. VBA, VB и С# не взаимодействуют никак. От VB. Net мы отказались, слишком громоздко писать. И самая лучшая поддержка у C#. Вероятно он станет кроссплатформенным. Но и это уже вчерашний день когда мы говорим об office (не обязательно MSO, но и свободных). Сегодня и завтра облака + JS + JSON (взамен xml и/или совместно) + google sheet и/или office 360. Полагаю, что совсем скоро персональный софт потеряет смысл. Сегодня даже сложные и очень тяжелые графические программы у auto desk (fusion 360 например из autodesk 360) перешли в облака.  
Изменено: Ткач Александр - 24.10.2019 18:45:00
 
Выкладываю таблицу всех элементов ribbon mso excel: вкладки кнопки, всплывающие меню и т.д.
Есть имена и id. Скачал у MS в этом году. Возможно это самая полная таблица.
 
Добрый день! Недавно ко мне обратились с вопросом: Как вызвать в vba процедуру, которая назначена событию кнопки на ленте Ribbon?
Есть стандартная ситуация, когда в xml мы создаем кнопку. Например
Код
<button id="cmdMyButton" label="Моя кнопка" size="normal" imageMso="CreateReport" onAction="cmdMyButton_RibClick"/>
В VBA мы соответственно пишем код для события onAction
Код
Sub cmdMyButton_RibClick(control As IRibbonControl)
   Msgbox "Моя кнопка нажата"
End Sub
Теперь нужно вызвать эту процедуру из другого модуля VBA. Простой вызов
Код
Sub CallMyButton    
    'Вызываем
    Call cmdMyButton_RibClick
End Sub
выдаст ошибку, т.к. не определен control (IRibbonControl). Вопрос был в о том, как задать control  при вызове cmdMyButton_RibClick.
Для VBA события элементов управления ленты Ribbon недоступны.  Процедура Sub cmdMyButton_RibClick(control As IRibbonControl) инициируется при возникновении события элемента управления на ленте через закрытый код MS Office посредством callback или обратного вызова. Со стороны Ribbon при нажатии на кнопку поступает запрос к VBA на наличие процедуры cmdMyButton_RibClick. Если такая процедура есть, то она исполняется, а если нет, то поступает сообщение о том, что процедура не найдена. И вообщем это все, и какого-то особого значения не имеет. Со стороны VBA процедура  Sub cmdMyButton_RibClick(control As IRibbonControl) самая рядовая процедура, никак не привязанная ни к каким событиям, ни к каким элементам управления. И для VBA аргумент control As IRibbonControl любой возможный control типа IRibbonControl (если бы аргумент был control As ComboBox, то можно было передать любой ComboBox). Этим и можно воспользоваться.
Код
Sub CallMyButton()
    'Задаем виртуальный IRibbonControl
    Dim ctlVirtualControl As IRibbonControl
    
    'Вызываем
    Call cmdMyButton_RibClick(ctlVirtualControl)
End Sub
Суть проста. Создаем виртуальный VirtualControl, и передаем его в процедуру cmdMyButton_RibClick.
Аналогично можно вызвать любую другую процедуру, передав ее аргументам соответствующие значения.
Возможно моя заметка будет кому-нибудь интересна. Всем удачи)
Изменено: Ткач Александр - 04.12.2019 17:06:17
 
Александр, почему-то  
Код
'Перемещаем ссылку llPointer в объект objRib с помощью API процедуры RtlMoveMemory  
Call RtlMoveMemory(objRibbon, llPointer, LenB(llPointer))
выдает ошибку и закрывает книгу!
Изменено: VW3 - 01.02.2020 11:59:11
 
Добрый день.
VW3, вышлите мне файл на почту, я посмотрю.

контакт удален (см. правила форума) [МОДЕРАТОР]
 
Вот файл
 
Добрый день.
VW3, высылаю вам файл с обновленным кодом. Объяснения в коде VBA через #
 
Цитата
Ткач Александр написал:
Call cmdMyButton_RibClick(ctlVirtualControl)
Собственно не обязательно делать вспомогательную переменную для вызова. Её значение всё равно Nothing, следовательно, если внутри cmdMyButton_RibClick она не используется (а если используется при таком подходе будет ошибка), то можно просто вызвать
Код
Call cmdMyButton_RibClick(Nothing)
 
Цитата
Call cmdMyButton_RibClick(Nothing)
Добрый день.
Андрей VG полностью согласен с вами.
Однако я постарался показать суть, и надеюсь у меня получилось)
 
Цитата
Ткач Александр написал:
показать суть, и надеюсь у меня получилось)
Да, конечно. Спасибо!
 
Цитата
Ткач Александр написал: ...файл с обновленным кодом
Александр, Спасибо! Буду пробовать/испытывать!
 
здравствуйте, поделитесь пжл кодом для Ворда, чтобы кодом ВБА править риббон ленту на лету (при открытом документе Ворда) спс
 
Ципихович Эндрю, а на форумах по Word Вам не ответили?
 
я не спрашивал
 
Так начать лучше оттуда ))
 
Цитата
Юрий М написал:
Так начать лучше оттуда ))
Юрий, а есть ли смысл, если требуется
Цитата
Ципихович Эндрю написал:
кодом ВБА править риббон ленту на лету
:qstn:
Хотя конечно может быть под этим подразумевается банальное нечто скрыть/показать...
 
спасибо за ответ, тогда если не трудно, чтобы поставить все точки над И
поясните что при помощи VBA можно извлечь с Ribbon?
считать с неё данные?
мне бы хотелось на AutoOpen или по событию нажатия ПКМ повесить отображать то или иное содержимое в Ribbon
спс
 
Добрый день. Эндрю, если вы хотите создать свою ленту в Word, вам придется изучить эту тему.
В качестве поиска рекомендую использовать предложение Customize the ribbon word vba
В качестве старта предлагаю вам прочитать материал по ссылке: https://wordmvp.com/FAQs/Customization/Customising%20the%20Ribbon%20-%20Advanced.htm
Принцип построения Ribbon в MS Office идентичен - xml +vba.
Также вам нужно подобрать удобный редактор xml. В сети можно найти достаточно материалов на эту тему.
 
Цитата
Ципихович Эндрю написал:
мне бы хотелось на AutoOpen
Пример во влложении.
Цитата
Ципихович Эндрю написал:
по событию нажатия ПКМ
Покажите в файле такой обработчик события.
Страницы: Пред. 1 2 3 След.
Наверх