Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/LstBox - MsgBox со встроенным ListBox - Мир MS Excel

Старая форма входа
  • Страница 1 из 1
  • 1
Модератор форума: _Boroda_, китин  
Мир MS Excel » Вопросы и решения » Готовые решения » LstBox - MsgBox со встроенным ListBox (Excel)
LstBox - MsgBox со встроенным ListBox
Alex_ST Дата: Пятница, 02.12.2016, 15:00 | Сообщение № 1
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Захотелось мне пополнить свою коллекцию "полезняшек" аналогом MsgBox, но ListBox, которому список передаётся массивом, а выбор из списка производится по DblClick
В итоге я хочу сделать надстройку с Public-функцией LstBox, применяемой точно так же "легко и просто" как и MsgBox.
Элемент ListView, к сожалению, по умолчанию в MSForms отсутствует, надо подключать библиотеки и референсы. Поэтому для обеспечения лучшей переносимости кода с компа на комп и из приложения в приложение от его применения пришлось отказаться.
Поставленным себе условием было то, чтобы весь код был в одной процедуре, которую с минимальными доработками можно будет потом добавлять и использовать в других приложениях.
Поэтому UserForm с ListBox на ней решил создавать программно. Покумекал сам. Ребята здесь подмогли советами.
В общем, вот какая функция получилась:
Функция имеет один обязательный аргумент ListArray - массив значений, которые должны выводиться в LietBox'е на открывающейся форме, и опциональный аргумент Title - заголовок выводимой формы.
Функция возвращает строковую переменную - текст выбранного даблкликом пункта LietBox'а или пустую строку "" , если форму закрыли "крестиком".
Для проверки работы функции написал ещё пару процедур:
Всё, вроде бы, отлично работает!
НО! Функция доступна для прямого вызова (без указания файла и модуля, где она находится) только из модулей своего проекта VBA :(
А цель была такая, чтобы её можно было использовать свободно откуда угодно так же просто как и MsgBox
Попытался её разместить в стандартном модуле Personal.xls - из других файлов напрямую не видна
Запихнул в надстройку - всё равно она не доступна из других книг...
Конечно, процедура не большая и в крайнем случае можно её держать в Personal.xls и "по нужде" копировать в книги, где она будет применяться.
Но как-то это не красиво...
Есть у кого-нибудь мысли, как добиться прямой видимости функции?



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Пятница, 02.12.2016, 21:31
 
Ответить
СообщениеЗахотелось мне пополнить свою коллекцию "полезняшек" аналогом MsgBox, но ListBox, которому список передаётся массивом, а выбор из списка производится по DblClick
В итоге я хочу сделать надстройку с Public-функцией LstBox, применяемой точно так же "легко и просто" как и MsgBox.
Элемент ListView, к сожалению, по умолчанию в MSForms отсутствует, надо подключать библиотеки и референсы. Поэтому для обеспечения лучшей переносимости кода с компа на комп и из приложения в приложение от его применения пришлось отказаться.
Поставленным себе условием было то, чтобы весь код был в одной процедуре, которую с минимальными доработками можно будет потом добавлять и использовать в других приложениях.
Поэтому UserForm с ListBox на ней решил создавать программно. Покумекал сам. Ребята здесь подмогли советами.
В общем, вот какая функция получилась:
Функция имеет один обязательный аргумент ListArray - массив значений, которые должны выводиться в LietBox'е на открывающейся форме, и опциональный аргумент Title - заголовок выводимой формы.
Функция возвращает строковую переменную - текст выбранного даблкликом пункта LietBox'а или пустую строку "" , если форму закрыли "крестиком".
Для проверки работы функции написал ещё пару процедур:
Всё, вроде бы, отлично работает!
НО! Функция доступна для прямого вызова (без указания файла и модуля, где она находится) только из модулей своего проекта VBA :(
А цель была такая, чтобы её можно было использовать свободно откуда угодно так же просто как и MsgBox
Попытался её разместить в стандартном модуле Personal.xls - из других файлов напрямую не видна
Запихнул в надстройку - всё равно она не доступна из других книг...
Конечно, процедура не большая и в крайнем случае можно её держать в Personal.xls и "по нужде" копировать в книги, где она будет применяться.
Но как-то это не красиво...
Есть у кого-нибудь мысли, как добиться прямой видимости функции?

Автор - Alex_ST
Дата добавления - 02.12.2016 в 15:00
Alex_ST Дата: Пятница, 02.12.2016, 15:07 | Сообщение № 2
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
К стати, для преобразования кода процедур, скопированного в буфер обмена, в стринг, который можно программно выводить через MsgBox , Debug.Print или ещё куда надо, я слепил ещё одну полезную процедурку:

Юзать проще простого: скопировал нужный текст или код, вызвал процедуру, набрал на клаве Debug.Print или MsgBox и нажал Ctrl+V



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Пятница, 02.12.2016, 19:31
 
Ответить
СообщениеК стати, для преобразования кода процедур, скопированного в буфер обмена, в стринг, который можно программно выводить через MsgBox , Debug.Print или ещё куда надо, я слепил ещё одну полезную процедурку:

Юзать проще простого: скопировал нужный текст или код, вызвал процедуру, набрал на клаве Debug.Print или MsgBox и нажал Ctrl+V

Автор - Alex_ST
Дата добавления - 02.12.2016 в 15:07
SLAVICK Дата: Пятница, 02.12.2016, 15:10 | Сообщение № 3
Группа: Модераторы
Ранг: Старожил
Сообщений: 2290
Репутация: 766 ±
Замечаний: 0% ±

2019
у кого-нибудь мысли, как добиться прямой видимости функции?

Подключить библиотеку функции к проекту: вот


Иногда все проще чем кажется с первого взгляда.
 
Ответить
Сообщение
у кого-нибудь мысли, как добиться прямой видимости функции?

Подключить библиотеку функции к проекту: вот

Автор - SLAVICK
Дата добавления - 02.12.2016 в 15:10
Alex_ST Дата: Пятница, 02.12.2016, 15:22 | Сообщение № 4
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Спасибо, Слава. Как надстройку-то я сохранил, а вот ребутнуть Excel и в "Надстройках" и референсах подключить забыл.
Сейчас попробую.
_______________________
Не вышло: в референсах с чем-то конфликтует, говорит, что имена какие-то задвоились, но не говорит какие.
Будем искать.



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Пятница, 02.12.2016, 15:36
 
Ответить
СообщениеСпасибо, Слава. Как надстройку-то я сохранил, а вот ребутнуть Excel и в "Надстройках" и референсах подключить забыл.
Сейчас попробую.
_______________________
Не вышло: в референсах с чем-то конфликтует, говорит, что имена какие-то задвоились, но не говорит какие.
Будем искать.

Автор - Alex_ST
Дата добавления - 02.12.2016 в 15:22
SLAVICK Дата: Пятница, 02.12.2016, 15:39 | Сообщение № 5
Группа: Модераторы
Ранг: Старожил
Сообщений: 2290
Репутация: 766 ±
Замечаний: 0% ±

2019
Там нужно просто в проекте VBA tools -- references -- browse
потом выбрать надстройку
и можно не перегружать excel


говорит, что имена какие-то задвоились, но не говорит какие.

может попробовать в новую книгу подключить, где нет макросов.
К сообщению приложен файл: 5783093.jpg (43.5 Kb)


Иногда все проще чем кажется с первого взгляда.
 
Ответить
СообщениеТам нужно просто в проекте VBA tools -- references -- browse
потом выбрать надстройку
и можно не перегружать excel


говорит, что имена какие-то задвоились, но не говорит какие.

может попробовать в новую книгу подключить, где нет макросов.

Автор - SLAVICK
Дата добавления - 02.12.2016 в 15:39
Alex_ST Дата: Пятница, 02.12.2016, 22:20 | Сообщение № 6
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Поковырялся дома. Получилось.
Оказывается, нужно было не только имя файла надстройки дать уникальное, но ещё и VBA Project Name, которое даётся всем проектам по умолчанию одинаковое - VBAProject, заменить на уникальное имя.
Сохранил файл как MyFunction.xla и переименовал проект в MyFunction.
Сначала в новом файле не заработало. Но потом, когда я назначил ссылку в референсах, заработало.
Вот и следующий вопрос: что сделать, чтобы ссылка на самодельную надстройку мапилась в референсах автоматически для всех открытых файлов?



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Пятница, 02.12.2016, 22:28
 
Ответить
СообщениеПоковырялся дома. Получилось.
Оказывается, нужно было не только имя файла надстройки дать уникальное, но ещё и VBA Project Name, которое даётся всем проектам по умолчанию одинаковое - VBAProject, заменить на уникальное имя.
Сохранил файл как MyFunction.xla и переименовал проект в MyFunction.
Сначала в новом файле не заработало. Но потом, когда я назначил ссылку в референсах, заработало.
Вот и следующий вопрос: что сделать, чтобы ссылка на самодельную надстройку мапилась в референсах автоматически для всех открытых файлов?

Автор - Alex_ST
Дата добавления - 02.12.2016 в 22:20
krosav4ig Дата: Суббота, 03.12.2016, 01:27 | Сообщение № 7
Группа: Друзья
Ранг: Старожил
Сообщений: 2347
Репутация: 989 ±
Замечаний: 0% ±

Excel 2007,2010,2013
слепил из того, что было
остается придумать откуда и по какому триггеру запускать AddReference
[vba]
Код
Option Explicit
Private Declare Function GetClassName& Lib "user32" Alias "GetClassNameA" (ByVal hwnd&, ByVal lpClassName$, ByVal nMaxCount&)
Private Declare Function AccessibleObjectFromWindow& Lib "oleacc" (ByVal hwnd&, ByVal dwId&, riid As GUID, xlWB As Object)
Private Declare Function GetDesktopWindow& Lib "user32" ()
Private Declare Function GetWindow& Lib "user32" (ByVal hwnd&, ByVal wCmd&)
Private Const GW_HWNDNEXT = 2
Private Const GW_CHILD = 5
Private Const OBJID_NATIVEOM = &HFFFFFFF0
Private Type GUID
    lData1 As Long
    iData2 As Integer
    iData3 As Integer
    aBData4(0 To 7) As Byte
End Type
Private IDispatch As GUID, oWnd As Window
Public Sub AddReference()
    Dim i&
    With IDispatch
        .lData1 = &H20400: .iData2 = &H0: .iData3 = &H0
        .aBData4(0) = &HC0: .aBData4(1) = &H0: .aBData4(2) = &H0
        .aBData4(3) = &H0: .aBData4(4) = &H0: .aBData4(5) = &H0
        .aBData4(6) = &H0: .aBData4(7) = &H46
    End With
    Referece2AllWorkbooks 0, "EXCEL7", 0, 0, 0, Application.UserLibraryPath & "MyFunction.xla"
    Set oWnd = Nothing
End Sub
Private Function Referece2AllWorkbooks&(hWndStart&, ClassName$, level&, lHolder&, lCnt&, sFile$)
    Dim hwnd&, sWindowTitle$, sClassName$, wb as Workbook
    If level = 0 Then
        If hWndStart = 0 Then
            hWndStart = GetDesktopWindow()
        End If
    End If
    
    'Increase recursion counter
    '--------------------------
    level = level + 1
    
    'Get first child window
    '----------------------
    hwnd = GetWindow(hWndStart, GW_CHILD)
    
    Do While hwnd > 0
        'Search children by recursion
        '----------------------------
        lHolder = Referece2AllWorkbooks(hwnd, ClassName, level, lHolder, lCnt, sFile)
        
        'get the class name
        '------------------
        sClassName = Space$(255)
        r = GetClassName(hwnd, sClassName, 255)
        sClassName = Left$(sClassName, r)
        
        If sClassName Like ClassName & "*" Or sClassName = ClassName Then
            Referece2AllWorkbooks = hwnd
            lHolder = hwnd
            AccessibleObjectFromWindow hwnd, OBJID_NATIVEOM, IDispatch, oWnd
            If Not oWnd Is Nothing Then
                If oWnd.Visible Then
                    lCnt = lCnt + 1
                    On Error Resume Next
                    For Each wb In oWnd.Application.Workbooks
                        wb.VBProject.References.AddFromFile sFile
                    Next
                End If
            End If
        End If
        
        'Get next child window
        '---------------------
        hwnd = GetWindow(hwnd, GW_HWNDNEXT)
    Loop
    Referece2AllWorkbooks = lHolder
    
End Function
[/vba]


email:krosav4ig26@gmail.com WMR R207627035142 WMZ Z821145374535 ЯД 410012026478460

Сообщение отредактировал krosav4ig - Суббота, 03.12.2016, 01:31
 
Ответить
Сообщениеслепил из того, что было
остается придумать откуда и по какому триггеру запускать AddReference
[vba]
Код
Option Explicit
Private Declare Function GetClassName& Lib "user32" Alias "GetClassNameA" (ByVal hwnd&, ByVal lpClassName$, ByVal nMaxCount&)
Private Declare Function AccessibleObjectFromWindow& Lib "oleacc" (ByVal hwnd&, ByVal dwId&, riid As GUID, xlWB As Object)
Private Declare Function GetDesktopWindow& Lib "user32" ()
Private Declare Function GetWindow& Lib "user32" (ByVal hwnd&, ByVal wCmd&)
Private Const GW_HWNDNEXT = 2
Private Const GW_CHILD = 5
Private Const OBJID_NATIVEOM = &HFFFFFFF0
Private Type GUID
    lData1 As Long
    iData2 As Integer
    iData3 As Integer
    aBData4(0 To 7) As Byte
End Type
Private IDispatch As GUID, oWnd As Window
Public Sub AddReference()
    Dim i&
    With IDispatch
        .lData1 = &H20400: .iData2 = &H0: .iData3 = &H0
        .aBData4(0) = &HC0: .aBData4(1) = &H0: .aBData4(2) = &H0
        .aBData4(3) = &H0: .aBData4(4) = &H0: .aBData4(5) = &H0
        .aBData4(6) = &H0: .aBData4(7) = &H46
    End With
    Referece2AllWorkbooks 0, "EXCEL7", 0, 0, 0, Application.UserLibraryPath & "MyFunction.xla"
    Set oWnd = Nothing
End Sub
Private Function Referece2AllWorkbooks&(hWndStart&, ClassName$, level&, lHolder&, lCnt&, sFile$)
    Dim hwnd&, sWindowTitle$, sClassName$, wb as Workbook
    If level = 0 Then
        If hWndStart = 0 Then
            hWndStart = GetDesktopWindow()
        End If
    End If
    
    'Increase recursion counter
    '--------------------------
    level = level + 1
    
    'Get first child window
    '----------------------
    hwnd = GetWindow(hWndStart, GW_CHILD)
    
    Do While hwnd > 0
        'Search children by recursion
        '----------------------------
        lHolder = Referece2AllWorkbooks(hwnd, ClassName, level, lHolder, lCnt, sFile)
        
        'get the class name
        '------------------
        sClassName = Space$(255)
        r = GetClassName(hwnd, sClassName, 255)
        sClassName = Left$(sClassName, r)
        
        If sClassName Like ClassName & "*" Or sClassName = ClassName Then
            Referece2AllWorkbooks = hwnd
            lHolder = hwnd
            AccessibleObjectFromWindow hwnd, OBJID_NATIVEOM, IDispatch, oWnd
            If Not oWnd Is Nothing Then
                If oWnd.Visible Then
                    lCnt = lCnt + 1
                    On Error Resume Next
                    For Each wb In oWnd.Application.Workbooks
                        wb.VBProject.References.AddFromFile sFile
                    Next
                End If
            End If
        End If
        
        'Get next child window
        '---------------------
        hwnd = GetWindow(hwnd, GW_HWNDNEXT)
    Loop
    Referece2AllWorkbooks = lHolder
    
End Function
[/vba]

Автор - krosav4ig
Дата добавления - 03.12.2016 в 01:27
Manyasha Дата: Суббота, 03.12.2016, 14:31 | Сообщение № 8
Группа: Модераторы
Ранг: Старожил
Сообщений: 2198
Репутация: 898 ±
Замечаний: 0% ±

Excel 2010, 2016
А у меня так получилось.
Следующий код нужно поместить в модуль ЭтаКнига надстройки. VBAProjectUserListBox заменить на имя вба-проекта надстройки (НЕ имя файла).
При подключении надстройки, во все открытые книги проставляются ссылки на нее (и при открытии новых). При отключении - все ссылки убиваются.
[vba]
Код
Private WithEvents App As Application
Private pathXlam As String
Private Sub Workbook_Open()
    Set App = Application
    Dim ref, Wbs As Workbook
    For Each ref In Application.VBE.VBProjects
        If ref.Name = "VBAProjectUserListBox" Then pathXlam = ref.Filename: Exit For
    Next ref
    
    On Error Resume Next
    For Each Wbs In Workbooks
        Wbs.VBProject.References.AddFromFile pathXlam
    Next Wbs
End Sub
Private Sub Workbook_AddinUninstall()
    Dim ref, Wbs As Workbook
    For Each Wbs In Workbooks
        For Each ref In Wbs.VBProject.References
            If ref.Name = "VBAProjectUserListBox" Then Wbs.VBProject.References.Remove ref
        Next ref
    Next Wbs
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
    On Error Resume Next
    Wb.VBProject.References.AddFromFile pathXlam
End Sub
Private Sub App_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
    Dim ref
    For Each ref In Wb.VBProject.References
        If ref.Name = "VBAProjectUserListBox" Then Wb.VBProject.References.Remove ref
    Next ref
End Sub
[/vba]

[p.s.]2003-го офиса у меня нет, проверяла только на 10-м[/p.s.]


ЯД: 410013299366744 WM: R193491431804
 
Ответить
СообщениеА у меня так получилось.
Следующий код нужно поместить в модуль ЭтаКнига надстройки. VBAProjectUserListBox заменить на имя вба-проекта надстройки (НЕ имя файла).
При подключении надстройки, во все открытые книги проставляются ссылки на нее (и при открытии новых). При отключении - все ссылки убиваются.
[vba]
Код
Private WithEvents App As Application
Private pathXlam As String
Private Sub Workbook_Open()
    Set App = Application
    Dim ref, Wbs As Workbook
    For Each ref In Application.VBE.VBProjects
        If ref.Name = "VBAProjectUserListBox" Then pathXlam = ref.Filename: Exit For
    Next ref
    
    On Error Resume Next
    For Each Wbs In Workbooks
        Wbs.VBProject.References.AddFromFile pathXlam
    Next Wbs
End Sub
Private Sub Workbook_AddinUninstall()
    Dim ref, Wbs As Workbook
    For Each Wbs In Workbooks
        For Each ref In Wbs.VBProject.References
            If ref.Name = "VBAProjectUserListBox" Then Wbs.VBProject.References.Remove ref
        Next ref
    Next Wbs
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
    On Error Resume Next
    Wb.VBProject.References.AddFromFile pathXlam
End Sub
Private Sub App_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
    Dim ref
    For Each ref In Wb.VBProject.References
        If ref.Name = "VBAProjectUserListBox" Then Wb.VBProject.References.Remove ref
    Next ref
End Sub
[/vba]

[p.s.]2003-го офиса у меня нет, проверяла только на 10-м[/p.s.]

Автор - Manyasha
Дата добавления - 03.12.2016 в 14:31
krosav4ig Дата: Суббота, 03.12.2016, 17:13 | Сообщение № 9
Группа: Друзья
Ранг: Старожил
Сообщений: 2347
Репутация: 989 ±
Замечаний: 0% ±

Excel 2007,2010,2013
а если запущено несколько экземпляров Excel, имхо, все же придется юзать winapi


email:krosav4ig26@gmail.com WMR R207627035142 WMZ Z821145374535 ЯД 410012026478460
 
Ответить
Сообщениеа если запущено несколько экземпляров Excel, имхо, все же придется юзать winapi

Автор - krosav4ig
Дата добавления - 03.12.2016 в 17:13
Alex_ST Дата: Суббота, 03.12.2016, 20:33 | Сообщение № 10
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Подумал и решил, что автоматическое прописывание референса на не стандартную функцию - ЗЛО.
Ведь если это сделать, то по привычке начнёшь применять LstBox точно так же на автомате как и MsgBox, а это при распространении написанного кода может привести к печальны последствиям.
Уж лучше прежде чем применять чуть подумать и прописать референс ручками если код пишешь для себя или перекинуть программный модуль в новый проект, если планируешь его кому-нибудь отдать.



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Суббота, 03.12.2016, 20:36
 
Ответить
СообщениеПодумал и решил, что автоматическое прописывание референса на не стандартную функцию - ЗЛО.
Ведь если это сделать, то по привычке начнёшь применять LstBox точно так же на автомате как и MsgBox, а это при распространении написанного кода может привести к печальны последствиям.
Уж лучше прежде чем применять чуть подумать и прописать референс ручками если код пишешь для себя или перекинуть программный модуль в новый проект, если планируешь его кому-нибудь отдать.

Автор - Alex_ST
Дата добавления - 03.12.2016 в 20:33
Мир MS Excel » Вопросы и решения » Готовые решения » LstBox - MsgBox со встроенным ListBox (Excel)
  • Страница 1 из 1
  • 1
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!