Условия: 1. Есть первый столбец со списком значений 2. Есть второй и третий (связанны) столбцы со списком значений 3. Второй столбец частично совпадает с первым, например:
первый столбец: Котельное оборудование Quasar D 24 i второй столбец: QUASAR D 24 i
Задача: Распределить данные по строкам из второго столбца по частичному совпадению с первым столбцом, т.е. пример на скриншотах было:
должно быть:
Условия: 1. Есть первый столбец со списком значений 2. Есть второй и третий (связанны) столбцы со списком значений 3. Второй столбец частично совпадает с первым, например:
первый столбец: Котельное оборудование Quasar D 24 i второй столбец: QUASAR D 24 i
Задача: Распределить данные по строкам из второго столбца по частичному совпадению с первым столбцом, т.е. пример на скриншотах было:
Вы уже на "Планете" написали, неужели трудно подождать с ответом? Я там уже Вам отписал, что делать. Ps. Без файла-примера в формате xls - Вам никто не поможет.
Вы уже на "Планете" написали, неужели трудно подождать с ответом? Я там уже Вам отписал, что делать. Ps. Без файла-примера в формате xls - Вам никто не поможет.LightZ
Задачу до конца автоматизировать не удастся. Либо время, потраченное на "полную" автоматизацию или на попытку такой автоматизации, будет экономически не оправдано. Поэтому на заключительном этапе придется немного поразбирать руками и глазами.
Схематично даю шаги решения, которые проделал я. Это больше даже себе узелок на память, нежели автору вопроса. Объяснять подробно ничего не буду, ибо как справедливо было замечено на другом форуме: в одном сообщении программировать на VBA не научить.
Прилагаемый к этому сообщению файл был получен на полном количестве строк оборудования и перед окончательным сохранением этот список на Листе1 был урезан до 2000 строк, чтобы уложиться в разрешенные к публикации на форуме 100 кб.
Итак, 1-й шаг - оценка объемов информации для обработки. Список оборудования - 6705 строк, список марок - 47 строк (подозреваю, далеко не полный). В процессе просмотра таблицы замечаю лишние пробелы между словами, поэтому
2-й шаг - сжатие пробелов соответствующей функцией в "Оборудовании" и в "Марках", результат - в колонках "Оборудование СЖПРОБЕЛЫ" и "Марка СЖПРОБЕЛЫ". В процессе просмотра таблицы таже было замечено большое количество повторяющихся строк оборудования, поэтому
3-й шаг - получение уникальных значений оборудования, при помощи расширенного фильтра по колонке Лист1!D ("Оборудование СЖПРОБЕЛЫ") и копировании отфильтрованных значений в колонку Лист3!A. Получилось 1022 уникальных значения из первоначальных 6705 строк. Что ж, сокращение внушительное, впору сказать: "Тыщу-то и глазками можно отсмотреть", но будем пытаться ужаться еще, поэтому
4-й шаг - написание макроса на VBA и его прогон. Макрос бежит по колонке Лист3!A ("Уникальные Оборудование СЖПРОБЕЛЫ"), в каждом значении оборудования ищет все значения марок из Лист1!E ("Марка СЖПРОБЕЛЫ"), при нахождении записывает конкретную марку напротив конкретного оборудования в соседнюю колонку Лист3!B ("Привязанные Марка СЖПРОБЕЛЫ").
5-й шаг - "перенос" значений марок в первоначальную таблицу, см. формулу в колонке Лист1!F ("Привязка Марки к Оборудованию") с использованием функций ИНДЕКС и ПОИСКПОЗ. Соотвественно, строки, где получился "0" (т.е. не получилась привязка) надо будет отфильтровать и попробовать привязать к ним марки вручную визуальным просмотром таблицы, поэтому неизбежен
6-й шаг - ручная привязка еще не привязанных марок.
Вот как-то так...
Задачу до конца автоматизировать не удастся. Либо время, потраченное на "полную" автоматизацию или на попытку такой автоматизации, будет экономически не оправдано. Поэтому на заключительном этапе придется немного поразбирать руками и глазами.
Схематично даю шаги решения, которые проделал я. Это больше даже себе узелок на память, нежели автору вопроса. Объяснять подробно ничего не буду, ибо как справедливо было замечено на другом форуме: в одном сообщении программировать на VBA не научить.
Прилагаемый к этому сообщению файл был получен на полном количестве строк оборудования и перед окончательным сохранением этот список на Листе1 был урезан до 2000 строк, чтобы уложиться в разрешенные к публикации на форуме 100 кб.
Итак, 1-й шаг - оценка объемов информации для обработки. Список оборудования - 6705 строк, список марок - 47 строк (подозреваю, далеко не полный). В процессе просмотра таблицы замечаю лишние пробелы между словами, поэтому
2-й шаг - сжатие пробелов соответствующей функцией в "Оборудовании" и в "Марках", результат - в колонках "Оборудование СЖПРОБЕЛЫ" и "Марка СЖПРОБЕЛЫ". В процессе просмотра таблицы таже было замечено большое количество повторяющихся строк оборудования, поэтому
3-й шаг - получение уникальных значений оборудования, при помощи расширенного фильтра по колонке Лист1!D ("Оборудование СЖПРОБЕЛЫ") и копировании отфильтрованных значений в колонку Лист3!A. Получилось 1022 уникальных значения из первоначальных 6705 строк. Что ж, сокращение внушительное, впору сказать: "Тыщу-то и глазками можно отсмотреть", но будем пытаться ужаться еще, поэтому
4-й шаг - написание макроса на VBA и его прогон. Макрос бежит по колонке Лист3!A ("Уникальные Оборудование СЖПРОБЕЛЫ"), в каждом значении оборудования ищет все значения марок из Лист1!E ("Марка СЖПРОБЕЛЫ"), при нахождении записывает конкретную марку напротив конкретного оборудования в соседнюю колонку Лист3!B ("Привязанные Марка СЖПРОБЕЛЫ").
5-й шаг - "перенос" значений марок в первоначальную таблицу, см. формулу в колонке Лист1!F ("Привязка Марки к Оборудованию") с использованием функций ИНДЕКС и ПОИСКПОЗ. Соотвественно, строки, где получился "0" (т.е. не получилась привязка) надо будет отфильтровать и попробовать привязать к ним марки вручную визуальным просмотром таблицы, поэтому неизбежен
6-й шаг - ручная привязка еще не привязанных марок.
Gustav, у Вас слишком много ненужного в файле, есть такие функции как LCase и Trim а с помощью двух массивов можно ускорить процесс выполнения. вот смотрите:
[vba]
Code
Sub io() Dim i&, j&, li& Dim Arr(), Arr2() Dim tm!: tm = Timer Application.ScreenUpdating = False
ReDim Arr(1 To [a2].CurrentRegion.Cells.Count, 1 To 2) ReDim Arr2(1 To Cells(Rows.Count, "g").End(xlUp).Row, 1) Arr = [a2].CurrentRegion.Value Arr2 = Range("g2:g" & Cells(Rows.Count, "g").End(xlUp).Row)
For i = 1 To UBound(Arr) For j = 1 To UBound(Arr2) If Trim(LCase(Arr2(j, 1))) Like "*" & Trim(LCase(Arr(i, 1))) & "*" Then Cells(j, "h").Value = Arr(i, 1) Cells(j, "i").Value = Arr(i, 2) li = li + 1 End If Next Next
Gustav, у Вас слишком много ненужного в файле, есть такие функции как LCase и Trim а с помощью двух массивов можно ускорить процесс выполнения. вот смотрите:
[vba]
Code
Sub io() Dim i&, j&, li& Dim Arr(), Arr2() Dim tm!: tm = Timer Application.ScreenUpdating = False
ReDim Arr(1 To [a2].CurrentRegion.Cells.Count, 1 To 2) ReDim Arr2(1 To Cells(Rows.Count, "g").End(xlUp).Row, 1) Arr = [a2].CurrentRegion.Value Arr2 = Range("g2:g" & Cells(Rows.Count, "g").End(xlUp).Row)
For i = 1 To UBound(Arr) For j = 1 To UBound(Arr2) If Trim(LCase(Arr2(j, 1))) Like "*" & Trim(LCase(Arr(i, 1))) & "*" Then Cells(j, "h").Value = Arr(i, 1) Cells(j, "i").Value = Arr(i, 2) li = li + 1 End If Next Next
Тогда уж так можно ещё ускорить, добавив третий массив (если нужно сохранить уже записанные значения, то можно создавать его из диапазона листа, а не генерить новый): [vba]
Code
Option Explicit
Sub io() Dim i&, j&, li& Dim Arr(), Arr2() Dim tm!: tm = Timer Application.ScreenUpdating = False
ReDim Arr(1 To [a2].CurrentRegion.Cells.Count, 1 To 2) ReDim Arr2(1 To Cells(Rows.Count, "g").End(xlUp).Row, 1) Arr = [a2].CurrentRegion.Value Arr2 = Range("g2:g" & Cells(Rows.Count, "g").End(xlUp).Row) ReDim arr3(1 To UBound(Arr2), 1 To 2) For i = 1 To UBound(Arr) For j = 1 To UBound(Arr2) If Application.Trim(UCase(Arr2(j, 1))) Like "*" & Application.Trim(UCase(Arr(i, 1))) & "*" Then arr3(j, 1) = Arr(i, 1) arr3(j, 2) = Arr(i, 2) li = li + 1 End If Next Next
Но правда из-за Application.Trim на 10 секунд замедлилось Но зато нашлось 2 упущенных совпадения! И исправил несовпадение строк по позиции в коде LightZ.
P.S. Чтоб многократно не повторять ресурсоёмкие операции, можно сделать так (время сразу упало на 0):
[vba]
Code
Sub io2() Dim i&, j&, li& Dim Arr(), Arr2() Dim tm!: tm = Timer Application.ScreenUpdating = False
ReDim Arr(1 To [a2].CurrentRegion.Cells.Count, 1 To 2) ReDim Arr2(1 To Cells(Rows.Count, "g").End(xlUp).Row, 1) Arr = [a2].CurrentRegion.Value Arr2 = Range("g2:g" & Cells(Rows.Count, "g").End(xlUp).Row) ReDim arr3(1 To UBound(Arr2), 1 To 2)
For i = 1 To UBound(Arr) Arr(i, 1) = Application.Trim(UCase(Arr(i, 1))) Next For i = 1 To UBound(Arr2) Arr2(i, 1) = Application.Trim(UCase(Arr2(i, 1))) Next For i = 1 To UBound(Arr) For j = 1 To UBound(Arr2) If Arr2(j, 1) Like "*" & Arr(i, 1) & "*" Then arr3(j, 1) = Arr(i, 1) arr3(j, 2) = Arr(i, 2) li = li + 1 End If Next Next
Тогда уж так можно ещё ускорить, добавив третий массив (если нужно сохранить уже записанные значения, то можно создавать его из диапазона листа, а не генерить новый): [vba]
Code
Option Explicit
Sub io() Dim i&, j&, li& Dim Arr(), Arr2() Dim tm!: tm = Timer Application.ScreenUpdating = False
ReDim Arr(1 To [a2].CurrentRegion.Cells.Count, 1 To 2) ReDim Arr2(1 To Cells(Rows.Count, "g").End(xlUp).Row, 1) Arr = [a2].CurrentRegion.Value Arr2 = Range("g2:g" & Cells(Rows.Count, "g").End(xlUp).Row) ReDim arr3(1 To UBound(Arr2), 1 To 2) For i = 1 To UBound(Arr) For j = 1 To UBound(Arr2) If Application.Trim(UCase(Arr2(j, 1))) Like "*" & Application.Trim(UCase(Arr(i, 1))) & "*" Then arr3(j, 1) = Arr(i, 1) arr3(j, 2) = Arr(i, 2) li = li + 1 End If Next Next
Но правда из-за Application.Trim на 10 секунд замедлилось Но зато нашлось 2 упущенных совпадения! И исправил несовпадение строк по позиции в коде LightZ.
P.S. Чтоб многократно не повторять ресурсоёмкие операции, можно сделать так (время сразу упало на 0):
[vba]
Code
Sub io2() Dim i&, j&, li& Dim Arr(), Arr2() Dim tm!: tm = Timer Application.ScreenUpdating = False
ReDim Arr(1 To [a2].CurrentRegion.Cells.Count, 1 To 2) ReDim Arr2(1 To Cells(Rows.Count, "g").End(xlUp).Row, 1) Arr = [a2].CurrentRegion.Value Arr2 = Range("g2:g" & Cells(Rows.Count, "g").End(xlUp).Row) ReDim arr3(1 To UBound(Arr2), 1 To 2)
For i = 1 To UBound(Arr) Arr(i, 1) = Application.Trim(UCase(Arr(i, 1))) Next For i = 1 To UBound(Arr2) Arr2(i, 1) = Application.Trim(UCase(Arr2(i, 1))) Next For i = 1 To UBound(Arr) For j = 1 To UBound(Arr2) If Arr2(j, 1) Like "*" & Arr(i, 1) & "*" Then arr3(j, 1) = Arr(i, 1) arr3(j, 2) = Arr(i, 2) li = li + 1 End If Next Next
Gustav, у Вас слишком много ненужного в файле, есть такие функции как LCase и Trim
Я же сказал, что не возражаю против улучшений. Да что там "не возражаю", я их искренне приветствую! У меня формулы, возможно избыточные (лишние, "ненужные"), возникали в ходе решения - хоть какого-то первого наброска решения. Зато с их помощью я по ходу видел промежуточные результаты и мог на их основе выбирать дальнейшее направление изысканий. Я не собирался оптимизировать свое решение. Я и так потратил на него (и на словесное оформление) пару своих кровных воскресных часов, за которые мне пока даже не сказали элементарного "спасибо". Ну да Бог с ним, если "заказчику" подходят мои рассуждения, то я рад. Если нет, то, как я уже сказал - узелок мне (а может и кому-то еще ) на память.
Про LCase и Тrim я, как ни странно, знаю. Даже знаю, что результат работы Trim не совпадает с результатом СЖПРОБЕЛЫ - смотрите в окне отладки: [vba]
Code
? Trim(" Сжаты ли пробелы? ") Сжаты ли пробелы?
[a1].Formula = "=TRIM("" Сжаты ли пробелы? "")" ? [a1].Value Сжаты ли пробелы?
[/vba]
Quote (LightZ)
Gustav, у Вас слишком много ненужного в файле, есть такие функции как LCase и Trim
Я же сказал, что не возражаю против улучшений. Да что там "не возражаю", я их искренне приветствую! У меня формулы, возможно избыточные (лишние, "ненужные"), возникали в ходе решения - хоть какого-то первого наброска решения. Зато с их помощью я по ходу видел промежуточные результаты и мог на их основе выбирать дальнейшее направление изысканий. Я не собирался оптимизировать свое решение. Я и так потратил на него (и на словесное оформление) пару своих кровных воскресных часов, за которые мне пока даже не сказали элементарного "спасибо". Ну да Бог с ним, если "заказчику" подходят мои рассуждения, то я рад. Если нет, то, как я уже сказал - узелок мне (а может и кому-то еще ) на память.
Про LCase и Тrim я, как ни странно, знаю. Даже знаю, что результат работы Trim не совпадает с результатом СЖПРОБЕЛЫ - смотрите в окне отладки: [vba]
Code
? Trim(" Сжаты ли пробелы? ") Сжаты ли пробелы?
[a1].Formula = "=TRIM("" Сжаты ли пробелы? "")" ? [a1].Value Сжаты ли пробелы?
LightZ, посмотри внимательно - массив берётся от второй строки, а результат выгружается точно по индексу массива. И на планете в файле тоже сдвиг - специально скачал глянул, там даже код не выполнял, там уже готовый результат со сдвигом.
LightZ, посмотри внимательно - массив берётся от второй строки, а результат выгружается точно по индексу массива. И на планете в файле тоже сдвиг - специально скачал глянул, там даже код не выполнял, там уже готовый результат со сдвигом.Hugo
что результат работы Trim не совпадает с результатом СЖПРОБЕЛЫ
Gustav, попробуйте запустить этот макрос, поймете разницу
[vba]
Code
Sub io() With Cells(1, 1) .Value = " s s " Cells(1, 2).Value = Application.Trim(.Value) MsgBox Len(Cells(1, 2)) Cells(1, 2).Value = Trim(.Value) MsgBox Len(Cells(1, 2)) End With End Sub
[/vba]
Hugo, а всё, понял. Просто изначально делал без заголовка столбцов
Quote (Gustav)
что результат работы Trim не совпадает с результатом СЖПРОБЕЛЫ
Gustav, попробуйте запустить этот макрос, поймете разницу
[vba]
Code
Sub io() With Cells(1, 1) .Value = " s s " Cells(1, 2).Value = Application.Trim(.Value) MsgBox Len(Cells(1, 2)) Cells(1, 2).Value = Trim(.Value) MsgBox Len(Cells(1, 2)) End With End Sub
[/vba]
Hugo, а всё, понял. Просто изначально делал без заголовка столбцов LightZ