Выбрать дату в календареВыбрать дату в календаре

Страницы: 1
Исключить ввод в TextBox более чем одной запятой., VBA EXCEL
 
Делаю программу на VBA которая работает с дробными числами. В моей форме существует TextBox в который пользователь вводит значения. Т.к. этот текст бокс создан исключительно для работы с числами я сделал определённую "заглушку" на ввод текста следующим образом:
Код
Private Sub TextBox_number_Change()
    If Me.TextBox_number.text <> "Дробное число" Then
        If Me.TextBox_number.text Like "*[!0-9,]*" Then
            Me.TextBox_number.text = Left(Me.TextBox_number.text, Len(Me.TextBox_number.text) - 1)
        End If
    End If
End Sub
Вся "заглушка" скрывается именно в 3 строчке кода. Если введенный знак не число или не запятая, то оно удаляется.
И вот тут вопрос: как сделать так, чтобы пользователю было разрешено вводить только 1 раз запятую?
Изменено: Юрий М - 10.09.2023 18:46:45
Перестал работать экспорт Диаграмм в excel, VBA EXCEL
 
Для своей программы мне понадобилось сделать создание диаграммы в листе Excel, затем экспорт этой диаграммы в .gif картинку, а затем вставка этой картинки на мою форму. В принципе всё получилось, всё работает, но вчера когда игрался с формой вылетела ошибка
Run-time error '-2147467259 (80004005)':
"Method 'Export' of Object '_Chart' Failed"

Код где возникает ошибка:
Код
Sub exportAndLoadDiagram(uf As EarthForm)
    'Скачиваем и закачиваем диаграмму
    Dim CurrentFileName As String
    CurrentFileName = Workbooks("Проект.xlsm").Path & "/current.gif"
    
    Dim MyChart As Chart
    Set MyChart = Workbooks("Проект.xlsm").Worksheets("Диаграмма грунтов пикета").ChartObjects("EarthOnPicketDiagram").Chart
    'Ошибка вот здесь
    MyChart.Export CurrentFileName, "GIF"
    
    uf.Image_earthOnPicket.Picture = LoadPicture(CurrentFileName)
    '=====================
    
    'Удаляем с листа диаграмму
    Workbooks("Проект.xlsm").Worksheets("Диаграмма грунтов пикета").Shapes("EarthOnPicketDiagram").Delete
End Sub
И самое интересное, что эта ошибка случается через раз. Иногда может случиться, а иногда нет. Полазив в интернете я увидел, что такая ошибка у людей с 2003+ года. Но толкового решения не нашёл. Может быть его и нету..
Может есть решение? Или подскажет кто-нибудь каким альтернативным способом можно экспортировать диаграмму в форму?
Кому интересно файл прикладываю
Изменено: Максим Белич - 02.09.2023 11:26:08
Почему происходит создание объекта 2 раза?, VBA EXCEL
 
Вопрос может показаться глупым для знатоков, но прошу объяснить что здесь происходит.
Есть 1 простая форма -> UserForm1
Данная форма запускается через кнопку на листе. Я поставил в процедуре инициализации обычный MsgBox чтобы отслеживать когда вызывается эта процедура.
При нажатии на кнопку на листе создаётся объект данной формы:
Код
Sub openForm()
    Dim obj As New UserForm1
    obj.Show
End Sub
После 3 строчки вызывается процедура UserForm_Initialize():
Код
Private Sub UserForm_Initialize()
    MsgBox "init userform1"
    Call Module1.proc("userform1")
End Sub
На экран выводится сообщение "init userform1".
Далее, вызывается другая процедура куда передаётся текст. Вот код этой процедуры "proc(text as String"
Код
Sub proc(text As String)
    If text = "userform1" Then
        Dim fm As UserForm1
        Set fm = UserForm1
    End If
End Sub
В данной процедуре proc я хочу присвоить ссылку на свою форму UserForm1 переменной fm, чтобы например добавить туда динамически какой-нибудь Control. Но почему-то после 4 строчки процедуры proc код перекидывается на процедуру UserForm_Initialize() и происходит новая отбивка MsgBox "init userform1" (т.е. по идее создаётся новый объект формы). И работая с переменной fm изменений в UserForm1 не происходит. А я ожидаю, что переменной fm присвоится уже открытая форма.
Прошу помощи сообщества в разборе этой логики работы VBA. Сам макрос прикладываю.
Создание диаграммы с накоплением с помощью VBA, VBA EXCEL
 
Хочу создать с помощью кода на vba 3д диаграмму с накоплением (пример - фото Пример.jpg)
С помощью макро рекордера записал последовательность действий и получил следующий код:
Код
Range("Таблица1").Select
    ActiveChart.ClearToMatchStyle
    ActiveChart.ClearToMatchStyle
    ActiveSheet.Shapes.AddChart2(286, xl3DColumnStacked100).Select
    ActiveChart.SetSourceData Source:=Range("Лист1!$I$2:$J$3")

Код прекрасно понимаю, хочу воссоздать всё сам, пишу следующее:
Код
    Dim obj As ListObject
    Set obj = Workbooks("Macro.xlsm").Worksheets("Лист1").ListObjects("Таблица1")
    Dim ch As Shape
    
    Set ch = ActiveSheet.Shapes.AddChart2(286, xl3DColumnStacked100)
    ch.Name = "my diagram"
   
    ch.Chart.SetSourceData Range("Лист1!" & obj.DataBodyRange.Address)
В итоге сколько бы раз я не пытался всегда получается диаграмма на картинке "Результат.jpg"

Это совсем не то, что ожидается. Может быть кто-то сталкивался с такой проблемой?
Изменено: Максим Белич - 30.08.2023 14:34:02
Рисование или подобие рисования в userform, На VBA
 
Пишу программу для работы.
Есть приложенный файл "Грунты.jpg". Вопрос стоит в следующем: пользователь в форме вводит все данные о грунтах в форму, они сохраняются (сейчас не важны нюансы), затем необходимо сделать так, чтобы при нажатии на кнопку запускался скрипт, который по ведённым данным от пользователя отрисует в форме что-то подобное, что и на картинке. Принимаются все идеи как это возможно сделать с помощью VBA в Excel.
Не прошу готового решения, а только идею, например, как бы вы это сделали.  
WithEvents для Label, VBA EXCEL
 
Динамически создаю несколько Label на своей UserForm. Т.к. создаю динамически нет возможности обратиться приватной процедурой в самой форме к определенному Label
Хочу сделать событие которое будет вызываться при клике на какой-либо Label.
Делаю так:
Создал класс LabelEventHandler
Там содержится следующий код:
Код
Private WithEvents lb As MSForms.Label



Private Sub lb_Click()
    MsgBox "click"
End Sub

Запускаю форму, кликаю на Label и ничего не происходит. Подскажите в чем дело.
Список названий столбцов в умной таблице, VBA
 
Есть умная таблица (ListObject). В данной таблице n-ое количество столбцов со своими названиями.
Какой есть просто способ или приём выгрузить эти названия столбцов и присвоить их в Combobox?
Сначала была идея сделать с помощью поля HeaderRowRange объекта ListObject, но в комбобокс почему-то переносится только название первой колонки, а необходимы все. Как можно это просто сделать? Желательно без всяких циклов и т.д)
Код
dim table as ListObject
Set table = Workbooks("Проект.xlsm").Worksheets("Лист1").ListObjects("MyTable")

Me.ComboBox_nameOfColumns.List = table.HeaderRowRange.value //!! В комбобоксе название только первой колонки объекта table! 
Как получить Range заголовка умной таблицы в VBA?
 
Есть объект obj типа ListObject. Для сортировки необходимо получить Range заголовка. Вопрос - как его получить?
Код
obj.ListColumns(1).DataBodyRange - возвращает "тело" таблицы под заголовком. Неподходит
obj.ListColumns(1).Range - возвращает весь Range (и заголовка и самой таблицы). Неподходит
Просто так крашится Excel и VBA, Automation Error
 
И снова здравствуйте, форумчане
Пишу для работы программу в экселе. Вчера сохранился, вышел, всё работало хорошо
Сегодня пришел и уже ничего не работает. (т.е. работает через раз, но чаще не работает  :) ). Файлы скину ниже (сначала открываем базу данных, затем проект и в макроредакторе открываем форму CAPOForm через F5 ну или F8). Скидываю архивом т.к. используется папка с иконками.

С самого начала появлялось MsgBox "Automation Error". Пытался найти причину на какой строке кода крашится программа. Выяснилось, что при Option Explicit у меня есть переменная без типа. Ну сделал ей тип.. на какое-то время заработало но не полностью (что-то загружалось, что-то нет)
Самое смешное, что даже если я банально делаю в коде VBA CTR-A и CTR-X - он просто вылетает со всеми открытыми книгами (файл поврежден?). Даже если нажимаю на кнопку стоп (RESET - синий квадратик) при не запущенном макросе он крашится.
Уже успел прочитать на просторах интернета про CodeCleaner, но у меня Windows 64-bit'ный и эксель, полагаю, тоже.
Также прочитал, что за MultiPage есть какой-то грешок ("MultiPage'и не могут обработать параметры выдаваемые им во время загрузки формы (могут только после загрузки формы").
Кто-нибудь знает что делать? Мой эксель и VBA всё?
Подскажите элегантное решение, Фильтрация 3-х и более столбцов с последующим получением информации через VBA
 
Здравствуйте. Вопрос требует вникнуть в задачу, поэтому буду благодарен за его изучение и уделенное время.
Нахожусь в поиске нормального решения для своей задачи. Данный пример приведён для простоты восприятия поставленной задачи
Есть умная таблица (List Object) (1 Фото.). В ней имеются 4 столбца. (Продукт | Цена | Размер коробки | Страна производства)

Конечная цель составить список на подобии тому, что приведено на фото 2. Т.е. нужно произвести фильтрацию по столбцам с последующим занесением информации в Word.

В данный момент времени вопроса о том, как занести это в Word нет. Вопрос в том, как красиво без решения "в лоб" сделать фильтрацию по 3 столбцам.
Т.е. необходимо сделать фильтрацию:
1) По столбцу Страна производства
Затем
2) Размер коробки
Затем
3) Цена
Взять информацию о продукте или продуктах. Затем по колонке цена необходимо сделать другой фильтр (если он там есть). Например в нашем примере другой фильтр имеется: Сначала идёт страна Индия, маленькая коробка, и имеется два вида цены (50 и 100). После того, как фильтры по цене закончатся необходимо поменять фильтр по полю "Размер коробки" и повторить все операции. Думаю логика задачи понятна.
Теперь о коде
С наскоку "родилось" следующее:



Код
Sub Макрос1()
    Dim country As New Collection
    Dim size As New Collection
    Dim price As New Collection
    
    Dim table As ListObject
    Set table = Workbooks("пробник.xlsm").Worksheets("Лист2").ListObjects("Таблица2")
    
    'Собираем все значения в столбце "Страна производства"
    Set country = getValuesInColumn(table, "Страна производства")
    'Собираем все значения в столбце "Размер коробки"
    Set size = getValuesInColumn(table, "Размер коробки")
    'Собираем все значения в столбце "Цена"
    Set price = getValuesInColumn(table, "Цена")
    
    Dim counterForCountry As Long
    Dim counterForSize As Long
    Dim counterForPrice As Long
    
    'Начинаем фильтровать колонку "Страна производства" по одному из доступных значений:
    For counterForCountry = 1 To country.Count
        'Если какой-то фильтр в таблице имелся - сбросим его
        If table.AutoFilter.FilterMode Then
            table.AutoFilter.ShowAllData
        End If
        
        table.DataBodyRange.AutoFilter 4, country(counterForCountry) '- теперь наша таблица отфильтрована по столбцу "Страна производства"
        
        'Начинаем фильтровать колонку "Размер коробки" по одному из доступных значений:
        For counterForSize = 1 To size.Count
            'Сбрасываем фильтр по данной колонке если он там был
            table.DataBodyRange.AutoFilter 3
            'Фильтруем по доступному полю из коллекции
            table.DataBodyRange.AutoFilter 3, size(counterForSize)
            
            'Начинаем фильтровать колонку "Цена" по одному из доступных значений:
            For counterForPrice = 1 To price.Count
                'Сбрасываем фильтр по данной колонке если он там был
                table.DataBodyRange.AutoFilter 2
                'Фильтруем по доступному полю из коллекции
                table.DataBodyRange.AutoFilter 2, price(counterForPrice)
                '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                'Прямо здесь у нас есть информация о продукте с которой мы можем что-либо сделать
                '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            Next counterForPrice
            'Сбрасываем фильтр по колонке "Цена"
            table.DataBodyRange.AutoFilter 2
        Next counterForSize
        'Сбрасываем фильтр по колонке "Размер коробки"
        table.DataBodyRange.AutoFilter 3
    Next counterForCountry
End Sub

'Функция, которая возвращает коллекцию значений без повторений в переданной таблице переданной колонке.
Function getValuesInColumn(table As ListObject, nameOfColumn As String) As Collection

    Set getValuesInColumn = New Collection
    
    On Error Resume Next
    Dim counter As Long
    Dim value As String
    For counter = 1 To table.ListRows.Count
            value = Intersect(table.ListRows(counter).Range, table.ListColumns(nameOfColumn).DataBodyRange).value
            getValuesInColumn.Add value, value
    Next counter
    
End Function
Это как раз-таки то самое решение в лоб - в итоге 3 цикла, все циклы находятся в друг друге и образовывается своеобразная матрёшка. А что если таких столбцов будет не 3, а 4 или 5? Очень легко где-то ошибиться.
И да, могут быть такие случаи, когда программа фильтрует столбец по значению, которого нет в фильтре, но который есть в коллекции. Т.е. например страна Индия, коробка маленькая, а цена 75. Такой цены нету и после фильтра в таблице становится 0 строк. Этот случай не стоит рассматривать.
Вопрос в том, как сделать код менее громоздким, более понятым.
Я новичок в VBA и могу не знать каких-то специальных "трюков" для таких задач. Буду рад увидеть любые решения и любой полёт фантазии!
Изменено: Максим Белич - 05.12.2022 12:03:01
Фильтрация умной таблицы используя VBA с последующим чтением информации, VBA
 
Есть простая умная таблица (ListObject). В ней всего 2 колонки: Фрукт и цена (1 фото)

Мне необходимо отфильтровать фрукты по цене (например показывать только те фрукты, которые стоят 100) и затем вывести их на экран.
Простыми манипуляциями делаю фильтр и пытаюсь вывести первую строку на экран (Фото 2)(по идее должно выводиться "100 Груша")
Но на экран выводится самая первая строка моей таблицы "200 Персик"

Есть ли способ после фильтрации как-то получить информацию из таблицы?

Способ с помощью цикла, чтобы пройтись по каждой строчке таблицы и сравнить его с нужным значением (в данном случае 100) не очень подходит, т.к. в реальном проекте необходимо последовательно вывести информацию из таблицы фильтруя по нескольким колонкам сразу.
Изменено: Максим Белич - 02.12.2022 16:09:41
Ран-тайм ошибка с методом Add объекта ListRows, VBA
 
Всем доброго времени суток. Надеюсь на помощь знающих. Ситуация простецкая, буду сильно благодарен за ваше уделенное внимание.
Чтобы сэкономить ваше время я убрал всё лишнее и упростил свою программу до простейших вещей - в моём проекте 2 книги (первая - База данных.xlsx, вторая Проект.xlsm). В базе данных содержится лишь один лист и одна таблица в которой записаны имена и возраст сотрудников.

Во второй книге у меня уже два листа. На первом листе расположена кнопка "Открыть первое меню".
При нажатии на эту кнопку появляется простейшая юзер-форма в которой есть кнопка на еще одно меню. Второе меню чуть-чуть сложнее. (фото - второе меню.jpg) Оно представляет из себя два листбокса и три кнопки.

Первый листбокс автоматически (при инициализации формы) загружается именами и возрастом, например сотрудников, из базы данных (моя первая книга). При нажатии на кнопку со стрелкой вниз имя и возраст человека перетаскиваются в листбокс "Выбранные имена".
Насколько мне известно программно задать названия колонок в листбоксе мы не можем. Он автоматически их берёт из шапки. Для этого и нужен второй лист книги "Проект.xlsm". На этом втором листе расположена таблица, в которую при нажатии на кнопку со стрелкой вниз помещается выделенный элемент листбокса (имя и возраст).

Далее для листбокса "Выбранные имена" я обновляю RowSource новым dataBodyRange.address таблицы на втором листе. Благодаря чему во втором листбоксе также присутствуют заголовки столбцов.
Стрелка вверх служит для удаления элементов из листбокса выбранных имён и удаления элемента из таблицы второго листа книги Проект.xlsm
Кнопка отмена полностью очищает таблицу второго листа и закрывает форму.

Всё это прекрасно работает до тех пор, пока не нажать несколько раз на кнопку со стрелкой вниз. Из ран-тайма вылетает ошибка
Method 'Add' of object 'ListRows' failed. Эксель виснет и закрывается. И вылетает эта ошибка когда захочет. Например в данном случае она вылетела на третий раз нажатия на кнопку со стрелкой вниз. Иногда это может быть на раз 5, 6.
А теперь самое интересное. Методом проб и ошибок я выяснил, что если добавить кнопку с панели "Разработчик" - "Вставить" - "Кнопка" именно на второй лист моей книги "Проект.xlsm" (обычную пустышку, без макроса) проблема почему-то исчезает! Занавес!
Прошу помочь разобраться в данной проблеме.
Изменено: Максим Белич - 23.11.2022 10:46:30
Всплывающая подсказка при нажатии на ячейку, VBA
 
Доброго времени суток

Делаю программу для упрощения своей работы. Нужна подсказка как можно реализовать отслеживание нажатия на ячейку в умной таблице в определенном столбце.

Имеется документ excel с разными листами. Самая основная таблица находится на первом листе. Скриншот №1. Пользователю даётся возможность заполнить данные о опоре через созданную юзер-форму. Все собранные данные от пользователя идут в главную таблицу, а также в другую таблицу на другом листе (Скриншот 2).Но, бывает, что до конца данные неизвестны и пользователь не может их ввести в юзер форме. Так и есть в моём примере: на втором скриншоте имеются пустые ячейки (пользователь не ввёл данные). Задача состоит в том, чтобы при нажатии на ячейку "Опора не готова" в первой таблице на первом скриншоте всплывала подсказка о том, какие данные еще необходимо заполнить (т.е. просто название столбцов со второй таблицы)
Логику сбора названий столбцов я сделал - собрал просто в строку. Далее пытался сделать комментарий к каждой ячейке "Опора не готова". Но полностью все данные в комментарий не влезают и часть обрезается.
Было бы красиво сделать, чтобы при НАЖАТИИ на ячейку с надписью "Опора не готова" моя собранная строка красиво показывалась.
Есть идея сделать эту функцию с шейпом (скриншот 3). Как его програмно создать, добавить в него текст мне известно. Но неизвестно как отследить нажатие на ячейку в таблице.  
Сортировка умной таблицы через код VBA, Sort data table using VBA
 
Доброго времени суток.
Как с помощью vba можно отсортировать умную таблицу по первому столбцу? Например как на фото - чтобы в таблице были только те строки, которые в первом столбце имеют надпись "Данные".
Как создать умную таблицу через код VBA?, Вопрос про создание умной таблицы через код VBA на неактивном листе
 
Доброго времени суток форумчане. Я являюсь новичком в написании макросов в vba поэтому прошу отнестись с пониманием:)

Для своей работы я пишу достаточную объёмную программу со внесением в таблицу данных через пользовательскую форму с последующей их обработкой. Мне необходимо, чтобы эти данные "перешли" в умные таблицы на других листах того же самого документа Excel. Но для начала эти умные таблицы необходимо создать.
Немного погуглив я нашел решение:
Код
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$1:$L$15"), , xlNo).Name = "МояТаблица1"
Всё прекрасно работает, таблица создается с диапазоном ячеек указанных в параметрах Range. Можно даже вместо ActiveSheet написать
Код
Workbooks("Mybook").Worksheets("MySheet")
И данный способ будет работать, но только в одном случае - если данный MySheet является активным в момент исполнения макроса. Если переключить активный лист на другой и попытаться запустить макрос, то будет ошибка:
Run-time error '1004':

Данные листа таблица должны находиться на том же листе, что и таблица.


Есть предположение, что сначала перед созданием умной таблицы в коде vba можно написать, чтобы нужный нам лист где должна располагаться будущая таблица стал активным. Но как и это сделать я пока тоже не знаю.

Решения своего вопроса на просторах в интернете я не нашел, поэтому решил спросить здесь. Буду благодарен за ваши ответы.
Изменено: Максим Белич - 22.07.2022 10:30:23
Страницы: 1
Наверх