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

Страницы: 1
Куда двигаться дальше?, Что учить, что читать и в какую сторону вообще пойти в VBA
 
всем доброго дня!
прошу помощи со стороны опытных посетителей и буду очень благодарен советам - по какому пути изучать VBA дальше?
я не разработчик, база экономика, но VBA интересен и собственно в деле нужен
читал форум, разбирал коды, изучал различные дискуссии постояльцев форума.
со словарем, массивами, коллекциями в принципе спокойно взаимодействую. синтаксис циклов понятен, обращение к объектам также
уровень не знаю своей, по всей видимости базовый/средний. могу нагуглить решение проблемы, если попадаю в ступор (как я слышал это хорошая способность;))
сейчас параллельно sql изучаю и буду пути взаимодействия с БД через VBA также изучать. да и сортировки интересно разобрать, но пока ограничения по времени свободному
чаще всего изучение чего-то нового наступает с появлением какой-либо задачи новой
посоветуйте с высоты вашего опыта в какую сторону в VBA продолжать движение и что учить дальше?
Оптимизация работы со словарем и его элементами. Изменение массива как элемента словаря, Вопросы по оптимизации и взаимодействию со словарем, массивами
 
testuser, благодарю! за выходные сам уже подразобрался. оказывается суть была достаточно проста
Оптимизация работы со словарем и его элементами. Изменение массива как элемента словаря, Вопросы по оптимизации и взаимодействию со словарем, массивами
 
Цитата
написал:
я делаю двумерный массив размером строк = количество ключей и столбцов  = максимальное количество значений по ключу. В словаре храню в качестве ключа - номер строки двумерного массива, а в качестве значения — индекс последнего заполненного столбца в этой строке.
если не трудно, сможете под данную вариацию пример кода показать? или под случай testuser, с хранением в элементах словаря индексы на элементы массивов
Показалось это интересным, с десяток тем на форуме просмотрел, но в голове как-то не укладывается суть подобных методов без явного примера
Оптимизация работы со словарем и его элементами. Изменение массива как элемента словаря, Вопросы по оптимизации и взаимодействию со словарем, массивами
 
МатросНаЗебре, спасибо. Попробую этот вариант
Alex, Немного другое, но в будущем понадобится, благодарю
Оптимизация работы со словарем и его элементами. Изменение массива как элемента словаря, Вопросы по оптимизации и взаимодействию со словарем, массивами
 
Добрый день.

Дошел до момента, когда мне понадобился словарь для кода. Изучил широко известное: Исчерпывающее описание объекта Dictionary

Задача была следующая: Имеется диапазон (столбец) на листе № 1. Необходимо найти данные значения на листе № 2 в определенном столбце и вписать на лист № 1 соответствующие ему значения из столбцов 11 и 12 (со листа № 2 соответственно). Грубо говоря аналог ВПР посредством макроса.
Решил для пары ключ-элемент в качестве элемента использовать сначала массив со значениями Empty, Empty (если так делать нежелательно, то как это сделать оптимальнее?). Далее провести цикл по поиску соответствия ключей словаря со значениями в столбце № 20 из соответствующего массива (взят из листа № 2). И если ключ существует, то изменить соответствующие значения массива, который является элементами словаря. На этом моменте произошел ступор на полдня, так как элементы массива, который является элементом словаря - не изменялись и моя "умопомрачительная" канула в лету.
Единственный вариант выхода:
Скрытый текст
Весь код:
Скрытый текст

Появились некоторые вопросы:
Прямого доступа для изменения элементов массива, являющегося элементом словаря - нет?
Корректное ли взаимодействие между словарь-массив в коде и вообще конкретно в коде есть ли что-то, что может повлиять на снижение быстродействия при больших объёмах? Если, что-то на ваш опытный взгляд здесь можно изменить/оптимизировать, то буду благодарен, если укажете что.
В чем разница позднего и раннего связывания конкретно в быстродействии? Читал информацию, что раннее связывание несколько быстрее, но насколько это несколько больше - не указано.
Изменено: willturner - 24.01.2024 12:40:14
Заполнение динамического массива в цикле While...Wend, Необходимо заполнить массив в цикле While...Wend с постоянным увеличением элементов
 
Sanja, да, именно такой вариант мне нужен был. Благодарю. Забыл ответить своевременно
Немного откорректировал для себя (в цикле сделал сразу пересбор нужных столбцов из временного массива в основной)
Скрытый текст
Заполнение динамического массива в цикле While...Wend, Необходимо заполнить массив в цикле While...Wend с постоянным увеличением элементов
 
Цитата
написал:
Если память позволяет хранить массив, размером "с запасом", то объявляете с запасом, наполняете и выгружаете столько
А вот про это, если есть возможность можно пример? Или на основании моего кода, как это реализовать?
Не первый раз вижу в различных темах об объявлении массива с запасом, но в голову это просто не совсем укладывается (из-за неопытности или может терминологии)
То есть имеется в виду объявить статический массив с верхним пределом, который точно не будет достигнут?
Код
Dim Massiv1 (1 to 100000, 1 to 9)
Пробовал в своем случае это, но получал ошибку: "Can't assign to array"
Заполняю массив через UsedRange в цикле While...Wend.
Заполнение динамического массива в цикле While...Wend, Необходимо заполнить массив в цикле While...Wend с постоянным увеличением элементов
 
Sanja, то есть в любом случае массив нужно будет транспонировать я так понял.
А у Application.Transpose есть же ограничения по количеству элементов массива? Вроде бы не более 65536 строк
Массив в моем случае может превысить 70 тыс. строк, но точно верхней границей будет 100 тыс.
Заполнение динамического массива в цикле While...Wend, Необходимо заполнить массив в цикле While...Wend с постоянным увеличением элементов
 
Добрый день.
Ситуация следующая, я дошел до момента, когда всё таки нужно начинать использовать массивы для оптимизации работы макроса.
Каким образом в цикле While...Wend можно произвести заполнение массива на каждой итерации без очистки предыдущих данных массива?
То есть необходимо собрать все данные по циклу в массив и затем вставить их в mainwb.
ReDim Preserve, как я понял, переопределяет только последнюю размерность (столбцы).
Количество строк, которое в итоге получится будет не более 100 000. Столбцов точно будет 9.
Также вопрос, можно ли как то удалить необходимые столбцы уже в массиве, а не заниматься удалением столбцов в каждой открываемой циклом книге?
Код
Sub МассивТЕСТВБК()


Dim Massiv1() As Variant
Dim dimension1 As Long

Dim FilesToOpen
Dim x As Integer
Dim lastrowIMP As Long
Dim mainwbname As String, importwbname As String

Dim rCell As Range
Dim sMergeStr As String
Dim myCell As Range, myCell2 As Range, myPhrase As String, myPhrase1 As String
Dim lastrow As Long
Dim i As Long

mainwbname = ActiveWorkbook.Name

myPhrase = "Подраздел III.II Сведения о подтверждающих документах (справочно)"
myPhrase1 = "Подраздел III.I Сведения о подтверждающих документах"

FilesToOpen = Application.GetOpenFilename _
    (FileFilter:="Excel files(*.xls*),*.xls*", _
    MultiSelect:=True, Title:="Выберите EXCEL файлы")
    
If TypeName(FilesToOpen) = "Boolean" Then
    MsgBox "Не выбрано ни одного файла!"
    Exit Sub
End If

Application.ScreenUpdating = False
Application.DisplayAlerts = False

ReDim Massiv1(100000, 8)

x = 1

While x <= UBound(FilesToOpen)

    Set importwb = Workbooks.Open(Filename:=FilesToOpen(x))
    
    importwbname = importwb.Name
    With Worksheets(1).Range("AF9:BA9")
        For Each rCell In .Cells
            sMergeStr = sMergeStr & rCell.Text
        Next rCell
    End With
    
    Set myCell = ActiveSheet.UsedRange _
        .Find(myPhrase, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns)
    lastrowIMP = Worksheets(1).Cells(Rows.Count, 2).End(xlUp).Row

    Worksheets(1).Range("A" & (myCell.Row - 2) & ":BP" & lastrowIMP) _
        .EntireRow.Delete
    
    Set myCell2 = ActiveSheet.UsedRange _
        .Find(myPhrase1, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns)
    
    Worksheets(1).Range("A1:BP" & (myCell2.Row + 4)) _
        .EntireRow.Delete

    Workbooks(importwbname).Worksheets(1).Range("B1:C1, E1:M1, O1:R1, T1:V1, X1:Y1, AA1:AG1, AI1:AJ1, AL1:AR1, AS1:BP1") _
        .EntireColumn.Delete
    
    If WorksheetFunction.CountA(Worksheets(1).UsedRange) <> 0 Then
        lastrowIMP = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row
        Worksheets(1).Range("I1:I" & lastrowIMP) = sMergeStr

        Massiv1 = Worksheets(1).UsedRange.Value

        sMergeStr = ""
        importwb.Close SaveChanges:=False
        x = x + 1
    Else
        Application.CutCopyMode = False
        sMergeStr = ""
        importwb.Close SaveChanges:=False
        x = x + 1
    End If

Wend

Application.DisplayAlerts = True

dimension1 = UBound(Massiv1, 1) + 1
Workbooks(mainwbname).Worksheets(1).Range("A2:I" & dimension1) = Massiv1

Application.ScreenUpdating = True


End Sub




Изменено: willturner - 22.12.2023 16:27:59
Оптимизирование кода. Ошибка при выполнении, При выполнении кода Excel полностью перезапускается. Необходимо оптимизировать код
 
Евгений Смирнов, добрый день. Галочка по буферу, указанная вами - не активная. Попробовал только Copy - улучшений нет.
Произвел замеры - больше всего уходило времени на Find - примерно 11 секунд на книгу размером в +- 2000-3000 строк, открытие самой книги - примерно 2,5 сек., EntireColumn.Delete в 53 строке - 3,7 сек. !!!!!
После указания аргумента - SearchOrder:= xlByColumns - время сократилось, теперь примерно 1,7 секунд тратится на Find и преобразования.
Но проблема с долгим удалением столбцов не решена.
Также видимо будет лучшим решением все значения из открываемых книг вносить в двумерный массив и уже преобразования вести в нем. Но с массивами пока у меня идет достаточно туго. Так как размерность второго измерения массива мне известна, но размерность первого заранее неизвестна. Можно конечно определить заранее с запасом до 100 000, но не знаю как это скажется на производительности. Плюс не совсем понятно заполнение массивов (так как нужно заполнять из разных книг и разное количество строк в каждой книге). Создам лучше отдельную тему по работе с массивом.
Спасибо за помощь!  
Оптимизирование кода. Ошибка при выполнении, При выполнении кода Excel полностью перезапускается. Необходимо оптимизировать код
 
Добрый день.
При отработке данного кода (обрабатывались примерно 200 книг эксель), после пяти минут отработки эксель перезапускается и в пустой книге предлагает сохранить восстановленную последнюю версию файла в котором собирались все данные (mainwb). В этой восстановленной версии неполные результаты отработки кода (перенесены около 60 тысяч строк)
Подскажите как оптимизировать данный код и исправить ошибку с перезапуском. Excel 2016
Код
Sub ВБК()

Dim FilesToOpen
Dim x As Integer
Dim lastrowIMP As Long

Dim rCell As Range
Dim sMergeStr As String
Dim myCell As Range, myCell2 As Range, myPhrase As Variant, myPhrase1 As Variant
Dim lastrow As Long
Dim i As Long, colNum As Long

mainwb = ActiveWorkbook.Name

myPhrase = "Подраздел III.II Сведения о подтверждающих документах (справочно)"
myPhrase1 = "Подраздел III.I Сведения о подтверждающих документах"

FilesToOpen = Application.GetOpenFilename _
    (FileFilter:="Excel files(*.xls*),*.xls*", _
    MultiSelect:=True, Title:="Выберите EXCEL файлы")
    
If TypeName(FilesToOpen) = "Boolean" Then
    MsgBox "Не выбрано ни одного файла!"
    Exit Sub
End If

Application.ScreenUpdating = False
Application.DisplayAlerts = False

x = 1
While x <= UBound(FilesToOpen)
    Set importWB = Workbooks.Open(Filename:=FilesToOpen(x))
    
    With Worksheets(1).Range("AF9:BA9")
        For Each rCell In .Cells
            sMergeStr = sMergeStr & rCell.Text  'собираем текст из ячеек
        Next rCell
    End With
    
    Set myCell = ActiveSheet.UsedRange.Find(myPhrase)
    lastrowIMP = Worksheets(1).Cells(Rows.Count, 2).End(xlUp).Row

    With Range("A" & (myCell.Row - 2) & ":BP" & lastrowIMP)
        .EntireRow.Delete
    End With
    
    Set myCell2 = ActiveSheet.UsedRange.Find(myPhrase1)
    
    With Range("A1:BP" & (myCell2.Row + 4))
        .EntireRow.Delete
    End With
    
    Worksheets(1).Range("B1:C1, E1:M1, O1:R1, T1:V1, X1:Y1, AA1:AG1, AI1:AJ1, AL1:AR1, AS1:BP1") _
        .EntireColumn.Delete
    
    If WorksheetFunction.CountA(Worksheets(1).UsedRange) <> 0 Then
        lastrowIMP = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row
        Worksheets(1).Range("I1:I" & lastrowIMP) = sMergeStr
        Worksheets(1).UsedRange.Copy
        Workbooks(mainwb).Worksheets(1).Range("A2").Insert shift:=xlDown
        sMergeStr = ""
        importWB.Close SaveChanges:=False
        x = x + 1
    Else
        sMergeStr = ""
        importWB.Close SaveChanges:=False
        x = x + 1
    End If
    
Wend

Application.DisplayAlerts = True

Workbooks(mainwb).Worksheets(1).Columns(1).Delete

Workbooks(mainwb).Worksheets(1).Range("A1") = "№ документа"
Workbooks(mainwb).Worksheets(1).Range("B1") = "Дата документа"
Workbooks(mainwb).Worksheets(1).Range("C1") = "Код вида документа"
Workbooks(mainwb).Worksheets(1).Range("D1") = "Код валюты документа"
Workbooks(mainwb).Worksheets(1).Range("E1") = "Сумма документа"
Workbooks(mainwb).Worksheets(1).Range("F1") = "Код валюты контракта"
Workbooks(mainwb).Worksheets(1).Range("G1") = "Сумма контракта"
Workbooks(mainwb).Worksheets(1).Range("H1") = "Уникальный № контракта"

lastrow = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row

With Workbooks(mainwb).Worksheets(1).Range("A1:H" & lastrow)
    .WrapText = False
    .HorizontalAlignment = xlLeft
    .VerticalAlignment = xlCenter
    .Font.Name = "Times New Roman"
    .Font.Size = 10
    .Rows.AutoFit
    .Columns.AutoFit
    .Borders(xlEdgeLeft).LineStyle = xlContinuous
    .Borders(xlEdgeLeft).LineStyle = xlContinuous
    .Borders(xlEdgeBottom).LineStyle = xlContinuous
    .Borders(xlEdgeRight).LineStyle = xlContinuous
    .Borders(xlInsideHorizontal).LineStyle = xlContinuous
    .Borders(xlInsideVertical).LineStyle = xlContinuous
End With

Application.ScreenUpdating = True

End Sub
Изменено: willturner - 20.12.2023 17:52:10
Разделение числа на разряды пробелами, Необходимо разделить числа на разряды пробелами
 
Добрый день.
Имеется подобная функция:
Она разделяет получаемые значения (числа) на разряды пробелами, учитывая также десятичные числа.
То есть вывод при получении числа 1100000 будет 1 100 000,00
Но при получении функцией числа 1000 или 50000, 150000 и подобных выводятся соответственно значения: 1000,00, 50000,00, 150000,00 (необходимо же 1 000,00, 50 000,00, 150 000,00)
Подскажите каким образом изменить функцию для корректного вывода значений.
Код
Function SummaRazd(Num, Optional Delim = "") As String

SummaRazd = IIf(Num < 0, "-", "") & Replace$(Trim$(Format$(Abs(Num), Right("### ### ### ### ### ### ### ### ### ###,##0.00", Len(Abs(Num)) + (Len(Abs(Num)) - 1) \ 3))), " ", Delim)

End Function
Изменено: willturner - 07.12.2023 09:50:47
Вставить строки по условию
 
МатросНаЗебре, благодарю, первый вариант показался интересней.
Второй такой, для математиков :D  
Вставить строки по условию
 
Доброго времени суток.
Необходимо следующее: вставить пустые ячейки с соответствующим форматом в диапазон для выравнивания таблицы. То есть Ячейки "Обороты" и "Сальдо на конец*" как в левой, так и в правой табличной части должны находиться на одной строке. (вариант Как должно быть отразил на соответствующем листе книги).
Случая может быть два: либо в табличной части слева необходимо добавить пустых ячеек, либо справа.
Я пошел путем поиска последней заполненной ячейки в левой табличной части и правой и от этих значений отталкивался.
Т. е. необходимое число ячеек которые надо вставить = разнице в сдвиге между двумя значениями последних заполненных ячеек lastrow и lastrow1.
Эта разница может быть любым целым положительным числом.
Если сдвига нет - оставить как есть (то есть если исходный вариант как на листе как должно быть)

В данном случае моих знаний хватило на подобный код:
Код
Sub аТестВставкаЯчеек()
Dim lastrow As Long, lastrow1 As Long, i As Long, numdiff as long


lastrow = Worksheets(1).Cells(Rows.Count, 2).End(xlUp).Row
lastrow1 = Worksheets(1).Cells(Rows.Count, .End(xlUp).Row

If lastrow < lastrow1 Then
    numdiff = lastrow1 - lastrow
    For i = 1 To numdiff
        Worksheets(1).Range("A" & lastrow - 1 & ":F" & lastrow - 1).Insert shift:=xlShiftDown
        lastrow1 = lastrow + 1
    Next i
ElseIf lastrow > lastrow1 Then
    numdiff = lastrow - lastrow1
    For i = 1 To numdiff
        Worksheets(1).Range("G" & lastrow1 - 1 & ":L" & lastrow1 - 1).Insert shift:=xlShiftDown
        lastrow1 = lastrow1 + 1
    Next i
Else

End If

End Sub
Всё работает, но есть ли какой-то альтернативный путь решения данной задачи? Например через Do While… Loop
Или может какой-то иной способ, до которого я не додумался или не знаю.
Страницы: 1
Наверх