Vba excel объединение массивов
Какие операции я могу выполнять с arr1 и arr2 и сохранять результат в arr3, так что:
Два вопроса: (1) Важен ли порядок элементов в объединенном массиве? (2) Вы хотите исключить дублирование, если в обоих массивах появляется одно и то же значение? - JohnFx
1) элементы в arr1 - это имена, а в arr2 - значения, последние элементы в arr3 на самом деле являются парами значений имени, так что пока они парные, мне все равно, если они не в порядке. Надеюсь это ответит на твой вопрос. 2) Я думаю, что пункт 1 ответил на это, я позабочусь о дублирующих именах eleswhere. - Kevin Boyd
12 ответы
К сожалению, тип Array в VB6 не обладал всеми функциями razzmatazz. Вам в значительной степени придется просто перебирать массивы и вставлять их вручную в третий
Предполагая, что оба массива имеют одинаковую длину
Обновлено: Исправлен код. Извините за предыдущую версию с ошибками. Мне потребовалось несколько минут, чтобы получить доступ к компилятору VB6, чтобы проверить это.
ответ дан 19 окт '09, 16:10
Суммирование UBounds дает размер, отличный от одного, и индекс записи в выходной массив должен быть увеличен отдельно от индекса чтения в исходные массивы. Пусть это станет уроком того, насколько надоедливыми могут быть массивы VBA! - джтолле
Просто чтобы объяснить раздражающие массивы VBA . особенно при объединении Excel и VBA, главное, что вам нужно знать, это то, что массивы могут иметь произвольные нижние границы. Если вы не укажете один, то LB устанавливается настройкой Option Base. Но массивы, созданные с помощью Array () и ParamArrays, всегда имеют LB, равное 0. Массивы, передаваемые из Excel, всегда имеют LB, равное 1. Это не проблема при итерации одного массива - используйте For Each или LBound и UBound - но работая с двумя массивами. сразу внезапно означает, что вам нужно подумать о деталях, таких как границы и индексы . - джтолле
Я не рекомендую это, но по умолчанию LB может быть установлен на 1, если вы используете Option Base 1 - Майк Вудхаус
Я действительно ненавижу "Опционную базу". Это похоже на загадочное действие на расстоянии, модуль за модулем, просто чтобы не вводить нижнюю границу. Я знаю, что он появился раньше VB / VBA и когда-то был актуален . - джтолле
Я ошибался насчет LB массива, созданного с помощью Array (), в моем комментарии выше. Это is зависит от настройки Option Base. Однако ParamArrays - нет. - джтолле
How do I combine these arrays with the outcome of (2, 4, 5, 3, 7, 6) ?
Create a third array that is empty the size of both arrays combined, then loop through each array adding the items one by one.
FYI added an alternative to @ScottCraner 's comment how to combine two 1-dim arrays using the advanced possibilities of the Application.Index() function :-)
4 Answers 4
You could potentially Join() and concatenate your two arrays, and then Split() the result back to a new array:
Explanation:
Join() will return a string that has each element in the array (first parameter) delimited by a "," (second parameter). We concatenate those two joined arrays with one more comma to get a string like 2,4,5,3,7,6 . We then use Split() to turn that string back into an array telling Split() that the delimter is a comma "," .
One caveat is that the return will be a string, and as such may need to have some other work done to it when retrieving the values.
The return of Split() will be an array, but yes. the return of the JOIN() will be a string and if an element contains the delimiter being used, then the array returned by Split() will be spaghetti.
Ah! @ScottCraner That's a good caveat! It is totally hacky, but you know I love a good hacky one-liner.
FYI "You know I love a good hacky one-liner." - Added another solution to "joining two array" using Application.Index() as a one-liner and maintaining the original types of array values (As Index() results in 1-based results, I need a further ReDimming back to a zero-based array to maintain the orginal settings).
You could use arrayLists. This also provides for an easy sort if wanted.
Out of interest: is there a function comparable to Join() that can be applied on arrayLists, as e.g. Debug.Print Join(list1, "|") object would result in an Error 13 Type mismatch.
Joining two arrays
As an alternative to the correct and working approach proposed by Scott Craner
Create a third array that is empty the size of both arrays combined, then loop through each array adding the items one by one.
. I demonstrate a way to
- insert only the element(s) of the 2nd array by a loop into a main array, whereas
- the main array gets only restructured by a one liner via Application.Index() .
As this function would change results to a 1-based array, I redimension the array back to a zero-based one. Furthermore I added an optional display in the VBE's Immediate Window resulting to 2|4|5|3|7|6 values:
1st step: Simple demo with same array values as in OP (Insertion of 1 element)
2nd step: More generalized approach using a AddElem procedure
The above demo inserts only one element. Therefore I coded a AddElem procedure and a help function addedElems() to allow the insertion of more elements. Assumption is made that all 1-dim arrays are zero-based as in the original post; could be adapted easily btw :-)
Help function addedElems()
Example call
I changed the values of OP's second array slightly ( Array(2) ~> Array(20,21) to demonstrate the insertion of more elements, thus resulting in a combined Array(20,21,2,4,5,3,7,6) .
Related link
Similarly you can study some pecularities of the Application.Index() function applied on 2-dim arrays at Insert first column in datafield array without loops or API calls
What kind of operations can I perform on arr1 and arr2 and assign the result to arr3 getting something like that:
Hint (due to comment): "1) the elements in arr1 are names and in arr2 are values, the final elements in arr3 are actually name-value pairs, so as long as they as paired I won't care if they are not in order."
Two questions: (1) Is the order of elements in the merged array important? (2) Do you want to eliminate dupes if the same value appears in both arrays?
1) the elements in arr1 are names and in arr2 are values the final elements in arr3 are actually name value pairs so as long as they as paired I wont care if they are not in order. Hope that answers your question. 2) I think point 1 answered this, I will be taking care of dupe names eleswhere.
17 Answers 17
For in case, the arrays contain a comma, can use Split(Join(arr1, Chr(1)) & Chr(1) & Join(arr2, Chr(1)), Chr(1))
Fyi Posted an extension to your fine solution, using the new ArrayToText() function and allowing to return numeric values as further benefit. @user3286479
Unfortunately, the Array type in VB6 didn't have all that many razzmatazz features. You are pretty much going to have to just iterate through the arrays and insert them manually into the third
Assuming both arrays are of the same length
Updated: Fixed the code. Sorry about the previous buggy version. Took me a few minutes to get access to a VB6 compiler to check it.
Summing the UBounds gives a size off-by-one, and the write index into the output array should be stepped separately from read index into the source arrays. Let this be a lesson in how annoying VBA arrays can be to work with!
Just to expound on annoying VBA arrays. especially when combining Excel and VBA, the main thing you need to know is that arrays can have arbitrary lower bounds. If you don't specifiy one, then the LB is set by the Option Base setting. But arrays created with Array() and ParamArrays always have a LB of 0. Arrays passed from Excel always have a LB of 1. It's no big deal when iterating a single array - use For Each or LBound and UBound - but working with two arrays at once suddenly means you have to think about details like bounds and indices.
I really hate "Option Base". It's like a mysterious action at a distance, module-by-module, just to avoid typing in a lower bound. I know it pre-dates VB/VBA, though, and was relevant once upon a time.
I was wrong about the LB of an array created with Array() in my comment above. It is affected by the Option Base setting. ParamArrays are not, though.
This function will do as JohnFx suggested and allow for varied lengths on the arrays
Note to anyone finding this. it actually merges the arrays. doesn't keep the order of the elements if that's important to you.
I tried the code provided above, but it gave an error 9 for me. I made this code, and it worked fine for my purposes. I hope others find it useful as well.
It work if Lbound is different than 0 or 1. You Redim once at start
My preferred way is a bit long, but has some advantages over the other answers:
- It can combine an indefinite number of arrays at once
- It can combine arrays with non-arrays (objects, strings, integers, etc.)
- It accounts for the possibility that one or more of the arrays may contain objects
- It allows the user to choose the base of the new array (0, 1, etc.)
Unfortunately there is no way to append / merge / insert / delete elements in arrays using VBA without doing it element by element, different from many modern languages, like Java or Javascript .
It's possible using split and join to do it, like a previous answer has showed, but it is a slow method and it is not generic.
For my personal use, I've implemented a splice functions for 1D arrays, similar to Javascript or Java. splice get an array and optionally delete some elements from a given position and also optionally insert an array in that position
Following the @johannes solution, but merging without loosing data (it was missing first elements):
To join Array1 and Array2, create a new array say JointArray
Suitable for 2 one dimensional arrays of same or different sizes. Results could be checked with Debug.Print Join(Array1, ",") Debug.Print Join(Array2, ",") Debug.Print Join(JointArray, ",")
I would like to adapt the great idea from user3286479 to work with arrays that came from single column ranges:
Here's a version that uses a collection object to combine two 1-d arrays and pass them to a 3rd array. Doesn't work for multi-dimensional arrays.
Or even a way that either variable can be uninitialised or an empty array or an array of objects (eg Dictionary objects). Only handles one dimension at a time, though. Also, it APPENDS arr2 to arr1 rather than merges.
I really appreciated Buggabill's and Daniel McCracken's responses. I needed a function to combine multidimensional arrays, but I'm sure I'll use Daniel's in the future. I made a couple mods to Buggabill's to 1) accommodate multidimensional arrays with a mix of variables and objects, and 2) merge the two arrays sequentially rather than meshed together (since the two arrays are combined in each step of the For loop). See the Was/Now examples below for an illustration.
Hope this helps some of you.
Extension on Split approach using ArrayToText() function (MS365)
If you dispose of MS/Excel 365 you may simplify joins & splits ( see @user3286479 's most upvoted post ) by passing a so called jagged array (a.k.a. as array of arrays) as main argument. This jagged array may comprise two or even more arrays, not only arr1 and arr2 .
As a further benefit I included the option to decide whether the array returns the merged array elements consecutively (default value additive=True ) or not (i.e. intertwined with explicit argument additive=False ).
Example call
Results in VB Editor's immediate window
Caveat
A possible disadvantage of the approach above is that all elements would be returned as strings, thus including all numeric values as well. To avoid this situation, you might use the following function alternatively using FilterXML() (available btw since vers. 2013):
В данной статье показаны 2 способа быстрого поиска значений в двумерных массивах. Поскольку искомое значение может встретиться в нескольких строках обрабатываемого двумерного массива, оба способа получают на выходе отфильтрованный двумерный массив. Способы формирования отфильтрованных массивов - разные: первый способ использует функцию ArrAutofilterEx второй способ - функцию .
Сортировка двумерного массива по нулевому столбцу Public Function CoolSort(SourceArr As Variant) As Variant ' сортировка двумерного массива по нулевому столбцу Dim Check As Boolean, iCount As Integer, jCount As Integer, nCount As Integer ReDim tmpArr(UBound(SourceArr, 2)) As Variant Do Until Check Check = True For iCount = LBound(SourceArr, 1) To UBound(SourceArr.
Надстройка предназначена для облегчения импорта данных в Excel из текстовых файлов с разделителями (например, из CSV) Пока во вложении - обычный файл Excel с нужными макросами, надстройку выложу позже В надстройке применена функция получения ссылки на заданную пользователем ячейку. Основой для надстройки послужила функция загрузки CSV файла в двумерный массив Использовать функции.
Надстройка с несколькими пользовательскими функциями вычислительной математики. Надстройка предназначена для тех пользователей, кто хочет: интерполировать табличные данные; находить корни уравнения; вычислять производные; численно интегрировать; аппроксимировать экспериментальные данные Внимание: 21 марта 2020 года выложена новая версия надстройки. Во вложении к статье - надстройка.
Функция TextFile2Array предназначена для преобразования файла CSV в двумерный массив Очень часто при работе с текстовыми файлами (и, в частности, с файлами CSV) приходится их загружать на лист Excel, предварительно производя фильтрацию данных в этом файле. Чтобы упростить весь процесс - от выбора файла CSV в диалоговом окне, до разбиения загруженного из файла текста в двумерный массив, и была.
Функция Array2XML формирует из исходной таблицы объект типа DOMDocument, который можно выгрузить в XML-файл одной строкой кода (метод Save) Sub XMLExport() Dim Заголовок As Range, Данные As Range Set Заголовок = Range("a1:f1") Set Данные = Range([A2], Range("A" & Rows.Count).End(xlUp)).Resize(, Заголовок.Columns.Count) arrHeaders = Application.
Если у вас есть таблица Excel, в которой, в определённом столбце, через запятую перечислены значения (или диапазоны значений), а вы хотите получить аналогичную таблицу, но чтобы в каждой строке было только одно значение, - то вам на помощь придёт функция ExtendArray. (пример работы функции можно увидеть на прикреплённом изображении) В своей работе ExtendArray использует функцию.
Функция предназначена для получения двумерного массива данных из видимых строк листа Excel. Например, нас интересует массив, начиная со второй строки, шириной 5 столбцов. Если все строки на листе - видимые, то все делается просто, одной строкой кода: arr = Range(Range("a2"), Range("a" & Rows.Count).End(xlUp)).Resize(, 5).Value А если на листе включен.
Sub ПримерИспользования() ' задаём полный путь к обрабатываемому файлу ПутьКФайлу$ = ThisWorkbook.Path & "\" & "Contract.XLS" Application.ScreenUpdating = False ' отключаем обновление экрана arr = LoadArrayFromWorkbook(ПутьКФайлу$, "a2", 30) ' загружаем данные ' выводим результаты в окно Immediate Debug.Print ".
Функция RandomRowsFromArray предназначена для выборки из двумерного массива случайных строк. К примеру, исходный массив (таблица) имеет размер 1000*20 (1000 строк, и 20 столбцов) Нам требуется выбрать из этой таблицы, случайным образом, 50 строк (получив, таким образом, таблицу размерами 50*20) Кроме того, необходимо, чтобы при каждом новом запуске макроса, в выборку попадали новые строки.
Функция принимает в качестве параметра arr двумерный массив, и разбивает его на несколько массивов, группируя строки по значению столбца SplitColumn& Сколько есть уникальных значений в столбце SplitColumn&, удовлетворяющих маске Mask$, - столько двумерных массивов будет возвращено функцией в виде коллекции Например, если есть исходный массив размерами 100*5, в котором во втором столбце.
Программа предназначена для анализа ожидаемой доходности различных портфелей (рассматриваются всевозможные комбинации проектов) При помощи формул типа =СЛЧИС() на листах с характеристиками проектов генерируются различные комбинации исходных значений, на основании которых формулами рассчитывается доходность проекта. Методом Монте-Карло формируются массивы значений (по одному массиву для.
Программа предназначена для еженедельного формирования плана проверок торговых точек. Функции программы: выборка из базы данных заданного числа случайных торговых точек, в соответствии с настройками для каждой группы формирование таблицы (файл Excel) со списком выбранных объектов по шаблону рассылка созданного файла (в архиве ZIP) по заданному списку адресов электронной.
Функция предназначена для сохранения двумерного массива в файл формата XLS Sub SaveArray(ByVal Arr, ByVal ColumnNames, ByVal DocName$) ' Получает двумерный массив Arr с данными, и массив заголовков столбцов ColumnNames. ' Создаёт новый файл в подпапке СФОРМИРОВАННЫЕ ДОКУМЕНТЫ с именем DocName$ On Error Resume Next ' создаём подпапку (там же, где текущий файл Excel).
какие операции я могу сделать на arr1 и arr2 и сохранить результат в arr3 такой, что:
к сожалению, тип массива в VB6 не имел всех функций razzmatazz. Вам в значительной степени придется просто перебирать массивы и вставлять их вручную в третий
предполагая, что оба массива имеют одинаковую длину
Обновлено: исправлен код. Извините за предыдущую версию багги. Мне потребовалось несколько минут, чтобы получить доступ к компилятору VB6, чтобы проверить его.
эта функция будет делать, как предложил JohnFx и учитывать различные длины на массивах
я попробовал код, указанный выше, но он дал мне ошибку 9. Я сделал этот код, и он отлично работал для моих целей. Я надеюсь, что и другие найдут его полезным.
он работает, если Lbound отличается от 0 или 1. Вы Redim один раз в начале
мой предпочтительный способ немного длинный, но имеет некоторые преимущества перед другими ответами:
- он может объединить неопределенное количество массивов сразу
- он может комбинировать массивы с не-массивами (объектами, строками, целыми числами и т. д.)
- он учитывает возможность того, что один или несколько массивов могут содержать объекты
- Это позволяет пользователю выбрать базу нового массива (0, 1 и т. д.)
к сожалению, нет возможности добавлять / объединять / вставлять / удалять элементы в массивах с помощью VBA, не делая этого по элементам, в отличие от многих современных языков, таких как Java или Javascript .
можно использовать split и join сделать это, как показал предыдущий ответ, но это медленный метод, и он не является общим.
для моего личного использования, я реализовал splice функции для массивов 1D, подобных Javascript или Java. splice вам массив и необязательно удалять некоторые элементы из заданной позиции, а также необязательно вставлять массив в эту позицию
вот версия, которая использует объект коллекции для объединения двух 1-d массивов и передачи их в 3-й массив. Не работает для многомерных массивов.
Читайте также: