Скачал отсюдафайл с макросами от ZVI, где Dictionary значительно превосходит Collection в скорости при удалении дублей в столбце с 60 000 ячеек. Создал список из 600 000 ячеек с 500 000 уникальных текстовых значений, загрузил их в массив и обработал двумя способами:
Подскажите, пожалуйста, в чем причина того, что Dictionary в моем случае работает медленнее.
Код:
Код
Option Explicit
Sub MegaArray()
Dim Base() As Variant, Base2() As Variant
Dim TimeS As Variant, TimeE As Variant
Base = ActiveSheet.Cells(1, 1).Resize(600000, 1).Value
Base2 = Base
TimeS = Time
Debug.Print "CollectionUniq start: " & UBound(Base) & " " & Date & " " & TimeS
CollectionUniq Base
TimeE = Time
Debug.Print "CollectionUniq end: " & UBound(Base) + 1 & " " & Date & " " & TimeE
TimeS = Time
Debug.Print "DictionaryUniq start: " & UBound(Base2) & " " & Date & " " & TimeS
DictionaryUniq Base2
TimeE = Time
Debug.Print "DictionaryUniq end: " & UBound(Base2) + 1 & " " & Date & " " & TimeE
End Sub
Public Sub CollectionUniq(ByRef StringArray() As Variant)
Dim x, y, arr, i As Long
ReDim arr(LBound(StringArray) To UBound(StringArray))
arr = StringArray
If IsArray(arr) Then
ReDim y(0 To UBound(arr))
With New Collection
On Error Resume Next
For Each x In arr
If Len(x) > 0 Then
Err.Clear
.Add 0, CStr(x)
If Err = 0 Then
y(i) = x
i = i + 1
End If
End If
Next
End With
End If
If y(i) = Empty Then
ReDim Preserve y(0 To i - 1)
End If
StringArray = y
End Sub
Public Sub DictionaryUniq(ByRef StringArray() As Variant)
Dim x, arr, y, i As Long
Dim Uniq_1D_Array() As Variant
ReDim arr(LBound(StringArray) To UBound(StringArray))
arr = StringArray
If IsArray(arr) Then
'With CreateObject("Scripting.Dictionary") ' Позднее связывание
With New Dictionary ' Раннее связывание, нужен Reference на MS Scripting Runtime
.CompareMode = vbTextCompare
ReDim y(0 To UBound(arr))
For Each x In arr
If Len(x) > 0 Then
If Not .Exists(x) Then
.Add x, 0
i = i + 1
y(i) = x
End If
End If
Next
Uniq_1D_Array = .Keys ' так можно получить сразу весь массив уникальных
End With
End If
StringArray = Uniq_1D_Array
End Sub
Столкнулся с такой задачей. В первом листе ("results") есть два столбца с исходными данными: A - с названиями, B - с числовыми значениями. Во втором листе ("base") размещена таблица с горизонтально сгруппированными названиями. В столбце D на листе "results" даны названия, для которых необходимо вывести сумму в столбце E, посчитанную в столбце B, на основе принадлежности к одной из групп на листе "base". Для определения группы нужно найти номер строки на листе "base" и, затем, посчитать сумму для всех значений в этой строке. Файл и скриншоты прилагаются. Заранее благодарен за любую помощь!
Не в первый раз сталкиваюсь с подобной проблемой, но никак не могу добавить регулярку в свой макрос. Пример подходящего кода от heso. Что касается макроса, то речь идет о выдаче значения "NF" (в ячейке I6), если искомый текст является частью просматриваемого, в случае если левый и/или правый символы (от вхождения искомого текста в просматриваемом) содержат либо буквы, либо цифры. Решил задачу Excel-формулами (в ячейке H6), но получилось длинновато. Заранее спасибо!
Возникла следующая проблема. Пытаюсь собрать все функции из диапазона C4:F4 в одну путем добавления функций из диапазона D4:F4 в C4. После замены F4, используемого в функции НАЙТИ в качестве исходного текста, в ячейке C4 на функцию из ячейки F4:
Код
(ВПР(types_names!$B4;types_names!$A:$D;4;0))
результат работы функции в ячейке C4 изменяется.
Заранее признателен всем, кто найдет возможность помочь!
Sub TownOpen()
Dim i As Long
Dim j As Long
Dim k As Integer
Dim l As Long
Dim iLastRow As Long
Dim FoundCell As Range
Dim FAdr As String
Dim a(), z As Long, ii As Long, x As Byte, tmp As String
Set sh = Workbooks("open_file.xlsm").Worksheets("one")
iLastRow = sh.Cells(Rows.Count, "A").End(xlUp).Row
folder = Workbooks("open_file.xlsm").Worksheets("two").Cells(1, 1)
fway = Dir(folder + "*.xls*")
While fway <> ""
Workbooks.Open(Filename:=folder + fway).RunAutoMacros Which:= _
xlAutoOpen
With ActiveWorkbook.Sheets(1)
For i = 1 To iLastRow
Set FoundCell = .Columns(3).Find(sh.Cells(i, "A"), , xlValues, xlWhole)
If Not FoundCell Is Nothing Then
FAdr = FoundCell.Address
n = 1
Do
j = j + 1
Workbooks("open_file.xlsm").Worksheets("three").Cells(j, n) = sh.Cells(i, "A")
Workbooks("open_file.xlsm").Worksheets("three").Cells(j, n + 1) = Cells(FoundCell.Row, "B")
Set FoundCell = .Columns(3).FindNext(FoundCell)
Loop While FoundCell.Address <> FAdr
End If
Next
End With
ActiveWorkbook.Close
a = Workbooks("open_file.xlsm").Worksheets("three").[a1].CurrentRegion.Value
ReDim b(1 To UBound(a), 1 To 2)
With CreateObject("Scripting.Dictionary")
For z = 1 To UBound(a)
tmp = a(z, 1) & "|" & a(z, 2)
If Not .exists(tmp) Then
.Item(tmp) = vbNullString
ii = ii + 1
For x = 1 To 2: b(ii, x) = a(z, x): Next
End If
Next
End With
Workbooks("open_file.xlsm").Worksheets("three").[a1].Resize(ii, 2) = b
fway = Dir()
Wend
End Sub
Он последовательно считывает XLS*-файлы из указанной папки, получая информацию из двух столбцов (путем сравнения значений из предварительно открытого списка). После обработки информации из каждого файла, дубликаты значений в двух столбцах должны удаляться (столбец 1 & столбец 2). С удалением дубликатов пока не все гладко) При обработке третьего файла, выдается следующая ошибка:
При нажатии на "Debug", подсвечивается строка:
Код
a = Workbooks("open_file.xlsm").Worksheets("three").[a1].CurrentRegion.Value
Кроме этого, данные, полученные после удаления дубликатов, располагаются не с первой строки:
Пытаюсь получить информацию из внешней книги. Макрос из open_file.xlsm открывает файл cities.xlsx, но информацию из него не обрабатывает. Помогите, пожалуйста!
Код макроса:
Код
Sub TownOpen()
Dim i As Long
Dim iLastRow As Long
Dim n As Integer
Dim FoundCell As Range
Dim FAdr As String
iLastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("B2:I" & iLastRow).ClearContents
FilePath = Sheets("Лист2").Cells(1, 1)
Workbooks.Open Filename:=FilePath
With Workbooks("cities.xlsx").Worksheets("cities")
For i = 2 To iLastRow
Set FoundCell = .Columns(3).Find(Cells(i, "A"), , xlValues, xlWhole)
If Not FoundCell Is Nothing Then
FAdr = FoundCell.Address
n = 2
Do
Cells(i, n) = Cells(i, "A")
Cells(i, n + 1) = .Cells(FoundCell.Row, "B")
Set FoundCell = .Columns(3).FindNext(FoundCell)
n = n + 2
Loop While FoundCell.Address <> FAdr
End If
Next
End With
End Sub
Скорее всего проблема в обращении к листу во внешней книге:
Код
With Workbooks("cities.xlsx").Worksheets("cities")
Подскажите, пожалуйста, как объединить два цикла в один. Заранее благодарен.
Первый:
Код
With Worksheets("source")
For i = 2 To iLastRow
Set FoundCell = .Columns(1).Find(Cells(i, "A"), , xlValues, xlWhole)
If Not FoundCell Is Nothing Then
FAdr = FoundCell.Address
n = 2
Do
Cells(i, n + 1) = .Cells(FoundCell.Row, "B")
Set FoundCell = .Columns(1).FindNext(FoundCell)
n = n + 2
Loop While FoundCell.Address <> FAdr
End If
Next
End With
Второй:
Код
With Worksheets("source")
For i = 2 To iLastRow
Set FoundCell = .Columns(1).Find(Cells(i, "A"), , xlValues, xlWhole)
If Not FoundCell Is Nothing Then
FAdr = FoundCell.Address
n = 2
Do
Cells(i, n) = .Cells(FoundCell.Row, "A")
Set FoundCell = .Columns(1).FindNext(FoundCell)
n = n + 2
Loop While FoundCell.Address <> FAdr
End If
Next
End With
Макрос целиком:
Код
Sub Town()
Dim i As Long
Dim iLastRow As Long
Dim n As Integer
Dim FoundCell As Range
Dim FAdr As String
iLastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("B2:I" & iLastRow).ClearContents
With Worksheets("source")
For i = 2 To iLastRow
Set FoundCell = .Columns(1).Find(Cells(i, "A"), , xlValues, xlWhole)
If Not FoundCell Is Nothing Then
FAdr = FoundCell.Address
n = 2
Do
Cells(i, n + 1) = .Cells(FoundCell.Row, "B")
Set FoundCell = .Columns(1).FindNext(FoundCell)
n = n + 2
Loop While FoundCell.Address <> FAdr
End If
Next
End With
With Worksheets("source")
For i = 2 To iLastRow
Set FoundCell = .Columns(1).Find(Cells(i, "A"), , xlValues, xlWhole)
If Not FoundCell Is Nothing Then
FAdr = FoundCell.Address
n = 2
Do
Cells(i, n) = .Cells(FoundCell.Row, "A")
Set FoundCell = .Columns(1).FindNext(FoundCell)
n = n + 2
Loop While FoundCell.Address <> FAdr
End If
Next
End With
End Sub
Решил попробовать создать динамический график вместо обычного. Столкнулся с двумя проблемами: 1. Даты на шкале выводятся числовыми значениями; 2. Информация из второй строки не используется.
Прикрепил пример. В первой вкладке график, который хотел бы получить. Во второй - попытка создать динамический график.
Подскажите, пожалуйста, возможно ли при помощи VBA обработать 50 миллионов строк (удалить дубликаты)? Источник: текстовый файл (с одним столбцом, без разделителей). Результат: список уникальных строк в Excel (менее одного миллиона), на одном листе. Спасибо.
Допустим, есть два листа ("sum" - первый, "10.05.2017_SONY" - второй). В первом листе есть ячейка A1 = "10.05.2017" и ячейка A2 = "SONY". В ячейку A3 первого листа нужно вставить значение из ячейки во втором:
Код
='10.05.2017_SONY'!A1
Возможно ли подставить значения ячеек A1 и A2 в ссылку на лист?
Как при помощи макроса загрузить данные из CSV-файлов по 4-м условиям в разные листы?
Условие 1 - Наименование товара Условие 2 - Страна Условие 3 - Дата Условие 3 - Вид оплаты (нал / безнал)
Количество столбцов с данными будет увеличиваться: два столбца на страну для определенной даты. Количество строк в каждом листе Excel-файла не более 200. Наименования товаров могут совпадать в разных листах.
Заранее благодарен за любую помощь!
Примеры отчета (Excel-файл) и исходных данных (CSV-файлы)
Function NSub(Txt As String, LTab As Range, Optional SNum As Long = 1, Optional RNum As Long = -1)
Dim q As Long, w As Long, wS1 As Long, v, t, kVo As Long, cNv As Integer, j As Long, sUm As Long
Dim strIn As String
Dim arrStr() As Variant, arrKey() As Boolean
Dim fLg As Boolean
NSub = Txt
ReDim arrStr(1 To Len(Txt), 1 To 2)
ReDim arrKey(1 To Len(Txt))
v = LTab.Value
For q = LBound(v) To UBound(v)
If Len(v(q, 1)) = 0 Then GoTo NXT1
kVo = (Len(Txt) - Len(Application.Substitute(LCase(Txt), LCase(v(q, 1)), ""))) / Len(v(q, 1))
If kVo < SNum Then GoTo NXT1
wS1 = 0
For i = SNum To kVo
w = InStr(1, Application.Substitute(Application.Substitute(LCase(Txt), "|", "@"), LCase(v(q, 1)), "|", i), "|")
fLg = True
For j = w To (w + Len(v(q, 1)) - 1)
If arrKey(j) Then fLg = False: Exit For
Next j
If fLg Then
arrStr(w, 1) = v(q, 1)
arrStr(w, 2) = v(q, 2)
For j = w To (w + Len(v(q, 1)) - 1)
arrKey(j) = 1
Next j
wS1 = wS1 + 1
End If
If wS1 = RNum Then Exit For
Next i
NXT1:
Next q
For j = Len(Txt) To 1 Step -1
If Len(arrStr(j, 1)) Then
wS1 = Len(arrStr(j, 1)) - Len(LTrim(arrStr(j, 1)))
strIn = Mid(Txt, j + wS1, Len(arrStr(j, 1)) - wS1)
cNv = 0
If strIn = StrConv(strIn, vbUpperCase) Then
cNv = vbUpperCase
strIn = StrConv(arrStr(j, 2), vbUpperCase)
ElseIf strIn = StrConv(strIn, vbLowerCase) Then
cNv = vbLowerCase
strIn = StrConv(arrStr(j, 2), vbLowerCase)
ElseIf (Left(Trim(strIn), 1) = StrConv(Left(Trim(strIn), 1), vbUpperCase)) And _
(Right(Trim(strIn), Len(Trim(strIn)) - 1) = StrConv(Right(Trim(strIn), Len(Trim(strIn)) - 1), vbLowerCase)) Then
cNv = vbProperCase
ws2 = Len(arrStr(j, 2)) - Len(LTrim(arrStr(j, 2)))
strIn = Space(ws2) & StrConv(Left(LTrim(arrStr(j, 2)), 1), vbUpperCase) & StrConv(Right(LTrim(arrStr(j, 2)), Len(LTrim(arrStr(j, 2))) - 1), vbLowerCase)
End If
If cNv Then Txt = Left(Txt, j - 1) & strIn & Right(Txt, Len(Txt) - j + 1 - Len(arrStr(j, 1)))
End If
NXT2:
Next j
NSub = Txt
End Function
Подскажите, пожалуйста, как добавить дополнительный (Optional) числовой параметр для диапазона LTab, чтобы была возможность указать номер столбца в выбранном диапазоне ячеек?
Например, для диапазона A1:D2 параметр 1 должен указывать на столбец B, 3 - на D.
Объявить, наверное, нужно примерно так: Optional NLtab As Long = 1? Как передать выбранный диапазон для обработки данных?
Есть пользовательская функция, при помощи которой происходит замена значений в ячейке. Как сделать так, чтобы замена значений происходила с учетом следующего правила: "Если пробелов по краям слова нет, значит это не слово, а часть слова, и замена не осуществляется."?
Недостаток этого подхода в том, что при замене придется отделять пробелами различные знаки в начале и в конце слов. Для этого подготовил набор знаков, которые, возможно, придется отделять (файл примера, вкладка "signs").
Еще один вопрос: Где удобнее и эффективнее разместить набор знаков? В отдельной вкладке или в самом макросе? Есть ли возможность использовать в пользовательских параметрах функции ключевое слово для определения того, что следующий за ним диапазон указывает на расположение набора знаков?
Пример:
Код
=NSub(A8;$D$8:$E$10;1;2;signs:signs!A1:A21)
В данном примере ключевое слово "signs:".
Если есть более простой способ для решения этой задачи, то было бы интересно узнать о нем.
Есть пользовательская функция, при помощи которой происходит замена значений в ячейке. Как сделать так, чтобы замена значений происходила с учетом обратных преобразований?
Пример: Исходный текст: красный
Таблица замен: красный ->синий синий -> красный В результате, исходный текст не меняется.
Есть пользовательская функция, при помощи которой происходит замена значений в ячейке с учетом регистра. Как сделать так, чтобы замена значений происходила и в случаях когда: 1. в исходном тексте первая буква заглавная, 2. все буквы в исходном тексте заглавные В остальных случаях должен сохраняться исходный текст.
Помогите, пожалуйста, решить задачу. В столбце A содержатся либо текстовые, либо числовые значения, которым присвоены порядковые номера в диапазоне B1:F19. В столбце H размещены порядковые номера, напротив которых, по совпадению с номерами в диапазоне B1:F19, должны быть выведены значения в столбце I. Мне удалось получить данные только для числовых значений:
В ячейке A1 размещен исходный текст, в B1 - текст, который нужно найти, в C1-XVD1 - начальные позиции всех вхождений текста из B1 (в каждой ячейке по одной начальной позиции). В принципе, все работает при помощи стандартных формул (см. пример), но боюсь, что при большом количестве вычислений использование макроса будет эффективнее. Заранее благодарю за помощь!
Нужна помощь для реализации автоматической сортировки по нескольким условиям (VBA): 1. Максимальное значение в столбце E для первой строки группы. 2. Сортировка по убыванию в рамках группы. 3. При равных значениях первых строк в столбце E, первой выводится наиболее многочисленная группа. 4. Если все условия в пункте 3 равны, то данные должны сортироваться по алфавиту в рамках первых двух условий.
В столбце А размещены фразы. В столбце B нужно (прошу не относить данное слово на свой счет) вывести уникальные слова из фраз, размещенных в столбце A. В столбце C выводится количество вхождений слов из столбца B во фразах из столбца A.
Здравствуйте, помогите решить вопрос, пожалуйста! Необходимо вставить данные по двум критериям. В столбцы B & C нужно вставить информацию из столбцов E:H после сопоставления названий и дат.