#excel #vba
#excel #vba
Вопрос:
Введение
Привет, переполнение стека. Я надеюсь получить ваш опыт по проблеме, с которой я иногда сталкиваюсь в Microsoft Excel. Пожалуйста, ознакомьтесь с контекстом и информацией, которые я представил вместе с моим вопросом ниже.
Пожалуйста, дайте мне знать, могу ли я уточнить, что я ищу, и / или могу ли я предоставить какие-либо дополнительные сведения.
Спасибо, как всегда! Это сообщество всегда является таким большим преимуществом.
Фон / контекст
Преобразование таблиц так, чтобы они содержали значения, хранящиеся в другой таблице
Мне часто приходится преобразовывать значения исходной таблицы (назовем их значениями «A») в соответствующее значение, хранящееся в другой таблице (значения «B»).
В зависимости от сложности, я обычно могу просто использовать обычный «Поиск / замена» или «VLOOKUP» или некоторую комбинацию из двух, если каждая ячейка содержит только одно значение.
Файлы, содержащие несколько значений в отдельных ячейках
В последнее время мне приходится преобразовывать несколько значений «A» (разделенных точками с запятой), хранящихся вместе в отдельных ячейках. Примечание: в сценариях «реального мира» обычно имеется около 200-300 строк и около 80 уникальных значений «A», поэтому обновление вручную не очень практично. Я попытался привести общую иллюстрацию ниже.
Иллюстрация
Для иллюстрации предположим, что каждое из отдельных значений в таблице 1 должно быть преобразовано в значения в соответствии с переходом, хранящимся в таблице 2.
Таблица 1: Исходные значения «A»
Значения ‘A’ |
---|
A123; A456; A789 |
A789; A098; A123 |
A456 |
A123; A456 |
A456 |
И так далее, примерно для 300 строк, с примерно 80 уникальными значениями |
Таблица 2: Переход: от значений «A» к значениям «B»
Значение «A» | Значение ‘B’ |
---|---|
A123 | B123 |
A456 | B456 |
A789 | B789 |
И так далее… | И так далее… |
Таблица 3: идеальный конечный результат (значения A, преобразованные в значения B)
Значения B |
---|
B123; B456; B789 |
B789; B098; B123 |
B456 |
И так далее… |
Анализ
Учитывая, что значения «A» хранятся вместе в таблице 1, такие методы, как поиск / замена или VLOOKUP в Excel, не сразу доступны для извлечения соответствующих значений «B».
У меня есть обходной путь, при котором я использую Excel «Text to Columns» для разделения строк таблицы 1 на отдельные ячейки, а затем использую VLOOKUP для извлечения значения «B», а затем использую функцию конкатенации, чтобы снова соединить строки вместе, но это хлопотно и подверженоиз-за человеческой ошибки.
Я повсюду искал ответы на эту тему, и мне еще не повезло найти кого-то, кто работает над той же проблемой.
Вопрос
Могу ли я каким-то образом автоматизировать весь или часть этого обременительного процесса с помощью чего-то вроде VBA для автоматической замены всех значений «A» в таблице 1 на соответствующие значения «B»? Я открыт для любых / всех потенциальных решений. Прямо сейчас я даже не уверен, с чего начать, или вообще разрешима ли моя проблема для начала.
Еще раз спасибо!
Ответ №1:
Вы определенно могли бы сделать что-то подобное с помощью VBA. Хотя, если вы еще не программист, я бы порекомендовал вам создать электронную таблицу с 4 вкладками:
- На первой вкладке есть исходные выходные данные (для справки и проверки)
- На второй вкладке снова вставьте данные и используйте текст для столбцов
- На третьей вкладке уже настроены vlookups
- На четвертой вкладке поместите свою таблицу vlookup
Теперь это становится двухэтапным процессом: вставьте данные, затем добавьте текст в столбцы. Надеюсь, это уменьшит человеческую ошибку
Опасности, на которые следует обратить внимание:
- Если у вас тысячи строк данных, вычисления могут быть слишком обременительными для вашего ноутбука. В этом случае установите вычисления вручную (см. Здесь https://www.ablebits.com/office-addins-blog/2017/06/29/excel-calculations-automatic-manual-iterative / ). Вам нужно будет нажать «Рассчитать сейчас», когда данные будут готовы.
- Текст в столбцах может перемещать ссылки на ячейки, что приводит к ошибкам #REF на вкладке формулы. Если это произойдет, то выполните текст в столбцах на первой вкладке и скопируйте во вторую
Комментарии:
1. VBA является противоположностью неуклюжему и был разработан для начинающих. Практически каждый современный язык во многом обязан своей душой прорывам, которые были заложены в BASIC. В вашем фактическом решении здесь нет ничего плохого, но ваш первый абзац следует удалить.
2. Мои извинения. Пожалуйста, смотрите Редакцию выше
3. Не беспокойтесь. Изменил мой понижающий голос на повышающий.
Ответ №2:
Замените несколько значений ячеек в таблицах с помощью словаря
Option Explicit
Sub replaceValues()
' Define constants.
Const dstName As String = "Sheet1"
Const dstTbl As String = "Table1"
Const dstCol As String = "A Values"
Const Delimiter As String = "; "
Const srcName As String = "Sheet2"
Const srcTbl As String = "Table2"
Const srcKey As String = "A Value"
Const srcVal As String = "B Value"
' Define workbook.
Dim wb As Workbook: Set wb = ThisWorkbook
' Write values from Source Column Ranges to Source Arrays.
Dim sKey As Variant ' Source Key Array
Dim sVal As Variant ' Source Value Array
With wb.Worksheets(srcName).ListObjects(srcTbl)
sKey = .ListColumns(srcKey).DataBodyRange.Value
sVal = .ListColumns(srcVal).DataBodyRange.Value
End With
' Write values from Source Arrays to Unique Dictionary.
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Dim i As Long ' Arrays Rows Counter
For i = 1 To UBound(sKey)
dict(sKey(i, 1)) = sVal(i, 1)
Next i
Erase sKey
Erase sVal
' Define Destination Column Range.
Dim rng As Range
With wb.Worksheets(dstName).ListObjects(dstTbl)
Set rng = .ListColumns(dstCol).DataBodyRange
End With
' Write values from Destination Column Range to Data Array.
Dim Data As Variant: Data = rng.Value
' Declare additional variables.
Dim cSplit() As String ' Current Split Array
Dim n As Long ' Current Split Array Element Counter
Dim cString As String ' Current String (in Split Array)
' Modify (replace) values in Data Array (using Unique Dictionary).
For i = 1 To UBound(Data, 1)
cSplit = Split(Data(i, 1), Delimiter)
For n = 0 To UBound(cSplit)
cString = cSplit(n)
If dict.Exists(cString) Then
cSplit(n) = dict(cString)
End If
Next n
Data(i, 1) = Join(cSplit, Delimiter)
Next i
' Write values from Data Array to Destination Column Range.
rng.Value = Data
End Sub