Генерация дубликатов строк

В большинстве случаев повторы в наших данных нежелательны и мы с вами стараемся от них избавиться разными способами. Но иногда случается, что дубликаты нужны и полезны, и более того - нам необходимо их создавать!

Допустим, что у нас есть вот такая таблица с именами людей, заказавших билет в кино и количеством билетов для каждого:

Исходные данные

Каждому билету нужно присвоить уникальный 6-значный номер, который формируется здесь простой функцией СЛУЧМЕЖДУ (RANDBETWEEN), генерирующей целое случайное число в заданном диапазоне 100000-999999. Да, я знаю, что теоретически совпадения могут быть, но вероятность очень невелика и пока нас, допустим, устраивает (кого не устраивает - см.эту статью). Проблема в другом: для тех, кто заказал больше одного билета, нужно вставить в таблицу новые строки-дубли (по количеству заказанных билетов), т.е. на выходе получить вот такое:

Генерация дубликатов строк

Руками такое делать - тоскливо, формулами - сложно. Так что остаются два наиболее удобных варианта - макросы и Power Query.

Способ 1. Создание дубликатов строк макросом

Откроем редактор макросов кнопкой Visual Basic на вкладке Разработчик (Developer) или сочетанием клавиш Alt+F11. Вставим новый модуль через меню Insert - Module и скопируем туда текст нашего макроса:

Sub Duplicate_Rows()
    Dim cell As Range

    Set cell = Range("B2")      'первая ячейка в столбце с кол-вом билетов
    Do While Not IsEmpty(cell)
        If cell > 1 Then
            cell.Offset(1, 0).Resize(cell.Value - 1, 1).EntireRow.Insert    'вставляем N пустых строк
            cell.Resize(cell.Value, 1).EntireRow.FillDown                   'заполняем вниз из первых ячеек
        End If
        Set cell = cell.Offset(cell.Value, 0)
    Loop
End Sub

Принцип тут не самый сложный: 

  1. проходим сверху-вниз по столбцу начиная с B2 до первой пустой ячейки
  2. если число в ячейке >1, то вставляем пустых строк под ячейкой на одну меньше, чем число билетов
  3. заполняем пустые ячейки (метод FillDown - аналог "протягивания за черный крестик" в правом нижнем углу ячейки)
  4. переходим к следующей ячейке и т.д.

Способ 2. Создание дубликатов строк в Power Query

Тем, кто хотя бы немного сталкивался с Power Query, рекламировать его мощь не нужно :) Для тех, кто не знаком (если коротко), то Power Query - это бесплатная надстройка для Excel от Microsoft, умеющая делать с данными практически все, что только можно себе представить: загрузку из любых источников, очистку, трансформацию, анализ данных и т.д. Для Excel 2010-2013 ее можно скачать с сайта Microsoft (появится отдельная вкладка Power Query после установки), а в Excel 2016 она уже встроена по-умолчанию (группа Получить внешние данные на вкладке Данные).

Power Query может легко и красиво решить нашу проблему с генерацией дубликатов.

Для начала, выделим нашу таблицу и загрузим ее в Power Query кнопкой Из таблицы/диапазона (From Table/Range) на вкладке Данные (Data) или Power Query:

Загрузка данных в Power Query

После окна подтверждения увидим редактор запросов и нашу таблицу. Добавим пользовательский столбец на вкладке Добавить столбец (Add Column - Custom Column):

Добавляем вычисляемый столбец

В появившемся окне введем имя столбца и формулу, которая создает список чисел от 1 до количества билетов в каждой строке:

Формула столбца

После нажатия на ОК появится новый столбец со списками, элементы которых можно развернуть в строки, используя кнопку в шапке таблицы:

Разворачиваем списки

В итоге, получаем практически то, что хотелось:

Сгенерированные дубликаты строк

Осталось удалить ненужный больше столбец Список (правой кнопкой мыши по заголовку - Удалить столбец) и выгрузить данные обратно на лист на вкладке Главная (Home) с помощью кнопки Закрыть и загрузить - Закрыть и загрузить в... (Close&Load - Close&Load to...) и указать подходящее место для результирующей таблицы:

Выгружаем на лист

И останется совсем простая часть - добавить к таблице столбец с формулой СЛУЧМЕЖДУ (RANDBETWEEN) для генерации случайных номеров билетов:

Результат

Особенно приятно, что при любых изменениях в исходной (левой) таблице (добавлении новых людей или изменении количества билетов), достаточно будет просто обновить правой кнопкой мыши нашу результирующую таблицу с номерами билетов.

P.S.

Если нужно, чтобы случайные числа не генерировались каждый раз заново при пересчете листа, а формировались один раз, сохраняя потом свои значения, то придется использовать макро-функцию StaticRandBetween из надстройки PLEX или что-то аналогичное.

Также можно, для наглядности, склеивать через дефис номер билета и порядковый номер из столбца Список прямо в Power Query, используя команду Объединить столбцы на вкладке Преобразование (Transform).

Ссылки по теме



25.09.2017 18:19:04
как-то просил тут на форуме помочь с макросом по той же проблеме. Вот он. Работает в выделенном диапазоне
Sub InsertRowsInNumders()
Dim a As Range, i&
Application.ScreenUpdating = 0
For Each a In Selection.Areas
        For i = a.Rows.Count To 1 Step -1
           If a.Cells(i) > 1 Then a.Cells(i + 1).Resize(a.Cells(i, 1).Value - 1).EntireRow.Insert Shift:=xlDown
        Next
Next
Application.ScreenUpdating = 1
End Sub
04.10.2017 09:59:28
Большое спасибо, Николай! Пригодилось в расчетах по логистике при повторах одинаковых грузов.
13.11.2017 16:24:46
Как изменить макрос для выделенного диапазона строк? В предыдущем ответе Jack Famous исходная информация не копируется.
25.12.2017 15:41:41
использовать другой макрос (вот этот) после предыдущего, или написать на форум для того, чтобы вам помогли их объединить
17.11.2017 11:13:09
Добрый день,

При попытке запустить Power Query, выдает такую ошибку.

Unexpected error: Cannot create process. NativeErrorCode:5
Details:
   Microsoft.Mashup.Evaluator.Interface.ErrorException: Cannot create process. NativeErrorCode:5 ---> Microsoft.Mashup.Evaluator.Interface.ErrorException: Cannot create process. NativeErrorCode:5 ---> System.ComponentModel.Win32Exception: Cannot create process. NativeErrorCode:5
  at Microsoft.Mashup.Evaluator.ContainerProcess.Start()
  at Microsoft.Mashup.Evaluator.ContainerFactory.Container..ctor(String exePath, String exitMutexName, Int32 containerId, Int32 maxWorkingSetInMB)
  at Microsoft.Mashup.Evaluator.ContainerFactory.CreateContainer()
  at Microsoft.Mashup.Evaluator.ContainerPoolContainerFactory.CreateContainer()
  at Microsoft.Mashup.Evaluator.RemoteEvaluationContainerFactory.CreateContainer()
  at Microsoft.Mashup.Evaluator.RemoteDocumentEvaluator.CreateContainer()Power Query
С чем бы это могло быть связано?
04.02.2023 03:16:57
Спасибо огромное!! Пригодилось когда нужно было дублировать размеры обуви по их количеству
Спасибо за статью! Мне как раз была промежуточная задача: есть столбец с числами: 98, 120, 80 и т.д. Надо было создать последовательности от 1 до 98, от 1 до 120, от 1 до 80 и т.д. Раньше это делали вручную (около 30тыс строк). Вот этот небольшой трюк с Power Query с генерацией списков {1..[Билетов]} очень помог.
Наверх