powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Функция возвращающая массив - как объявить
9 сообщений из 9, страница 1 из 1
Функция возвращающая массив - как объявить
    #39570941
Andrey A. Markine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!

Начал переписывать под VBA код из OOBasic и уперся - нужна функция, которая будет фильтровать массив строк по условию, и возвращать только нужные. Хотелось-бы чтобы возвращала она их массивом, а не строкой.

Не могу понять как это сделать на VBA - в OOBasic просто обозначаешь функцию As Array и все работает.
Здесь же ругается, хотя результирующий массив строиться нормально.

В оригинале объявление функции на OOBasic:

Код: vbnet
1.
Function aFilterArrayByCondition(sInputCSV As String, sCondition As String, sRowSeparator As String) As Array



Проблема еще и в том, что по OOBasic есть Питоньяк, а по VBA все что нахожу это в основном Excel, который мне не нужен.
У меня задача - считать данные из текстового файла и внести в документ Word

Сама функция ниже:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
Function aFilterArrayByCondition(sInputCSV As String, sCondition As String, sRowSeparator As String) As Variant()
    Dim iRows As Integer
    Dim iRowIndex As Integer
    Dim aInputArray() As String
    Dim sFilterArrayByCondition As String
    Dim sTransformString As String
    Dim sResultString As String
    Dim aResultArray() As String
    aInputArray() = Split(sInputCSV, sRowSeparator)
    iRows = UBound(aInputArray())
        For iRowIndex = 0 To iRows
            sTransformString = aInputArray(iRowIndex)
            If InStr(1, sTransformString, sCondition) And sResultString = "" Then
                sResultString = sTransformString
            ElseIf InStr(1, sTransformString, sCondition) And sResultString <> "" Then
                sResultString = sResultString & vbNewLine & sTransformString
            End If
        Next iRowIndex
    aResultArray() = Split(sResultString, sRowSeparator)
    aFilterArrayByCondition = aResultArray()
End Function



Заранее спасибо!
...
Рейтинг: 0 / 0
Функция возвращающая массив - как объявить
    #39571014
Казанский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrey A. Markine,
так объявлена уже: Function aFilterArrayByCondition(sInputCSV As String, sCondition As String, sRowSeparator As String) As Variant()

Чтобы вывести результат (массив) на лист в Excel, надо ввести функцию как формулу массива , см. Справку.
...
Рейтинг: 0 / 0
Функция возвращающая массив - как объявить
    #39571035
Hugo121
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Но функция возвращает одномерный массив, для Экселя это горизонтальный массив, чтоб вывести его в столбец - его нужно транспонировать.
Если делать именно для Экселя - можно сразу в функции формировать двумерный вертикальный массив, тогда не нужны будут дополнительные трансформации.
Но т.к. тут Экесель вообще ни при чём и не нужен - не понимаю в чём проблема с Вордом?
...
Рейтинг: 0 / 0
Функция возвращающая массив - как объявить
    #39571044
Andrey A. Markine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за ответы, но вообще-то я сразу честно написал что Excel мне не нужен ни разу.
Я никуда данные не вывожу – у меня весь код на VBA работает, только окончательный отчет выводится в Word.

Уже решил проблему, рабочий вариант, если кому нужно:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
Function aFilterArrayByCondition(sInputCSV As String, sCondition As String, sRowSeparator As String) As String()
    Dim iRows As Integer
    Dim iRowIndex As Integer
    Dim aInputArray() As String
    Dim sFilterArrayByCondition As String
    Dim sTransformString As String
    Dim sResultString As String
    Dim aResultArray() As String
    aInputArray() = Split(sInputCSV, sRowSeparator)
    iRows = UBound(aInputArray())
        For iRowIndex = 0 To iRows
            sTransformString = aInputArray(iRowIndex)
            If InStr(1, sTransformString, sCondition) And sResultString = "" Then
                sResultString = sTransformString
            ElseIf InStr(1, sTransformString, sCondition) And sResultString <> "" Then
                sResultString = sResultString & vbNewLine & sTransformString
            End If
        Next iRowIndex
    aResultArray() = Split(sResultString, sRowSeparator)
    aFilterArrayByCondition = aResultArray
End Function



Проблема была в () после aResultArray и несоответствии типов массивов.
Я думал что судя по описанию Variant() должен спокойно принимать любое значение, а оказывается нет.
...
Рейтинг: 0 / 0
Функция возвращающая массив - как объявить
    #39571099
Казанский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrey A. Markine,
функция в таком виде конечно возвратит массив, но только если sRowSeparator=vbNewLine .
Потому что sResultString собирается через разделитель vbNewLine , а делится через sRowSeparator . Иначе будет массив, но из одного элемента.
Вообще, то, что Вы хотите, как я понял, делается одной строкой:
Код: vbnet
1.
2.
3.
Function aFilterArrayByCondition(sInputCSV As String, sCondition As String, sRowSeparator As String) As String()
  aFilterArrayByCondition = Filter(Split(sInputCSV, sRowSeparator), sCondition)
End Function
...
Рейтинг: 0 / 0
Функция возвращающая массив - как объявить
    #39571102
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrey A. MarkineЯ думал что судя по описанию Variant() должен спокойно принимать любое значение, а оказывается нет.


Variant "по описанию" принимает любой тип.
Т.е. если бы вы определили возвращаемое значение As Variant - оно бы вполне "приняло" строковый массив.
И переменную, принимающую результат тогда тоже надо объявить как Variant.

Определение возвращаемого значения как variant() означает, что вы собрались возвращать массив, каждый элемент которого variant.
Массивы, содержащие элементы разных типов несовместимы по присвоению.
т.е. нельзя переменной типа variant() присвоить значение переменной типа string() и наоборот - типы элементов этих массивов разные а переменные, умеющие принять каждая свой массив оказываются несовместимы по типу принимаемого массива.

Andrey A. MarkineУже решил проблему, рабочий вариант, если кому нужно:

не похож он на рабочий. Т.е., наверно рабочий, но для единственного случая, когда параметр sRowSeparator имеет значение vbNewLine

вот вам "более рабочий":

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
Function aFilterArrayByCondition(sInputCSV As String, sCondition As String, sRowSeparator As String) As String()
    
    Dim aInputArray() As String
    aInputArray() = Split(sInputCSV, sRowSeparator)
    
    Dim i_filtered As Long
    i_filtered = -1&
    
    Dim iRows As Long
    iRows = UBound(aInputArray())
    
    If iRows >= 0 Then
    
        ReDim aResultArray(0 To iRows) As String
        Dim iRowIndex As Long
        
        For iRowIndex = 0 To iRows
            If InStr(1, aInputArray(iRowIndex), sCondition) Then
              i_filtered = i_filtered + 1
              aResultArray(i_filtered) = aInputArray(iRowIndex)
            End If
        Next iRowIndex
    End If
    
    If i_filtered >= 0 Then
      ReDim Preserve aResultArray(0 To i_filtered) As String
    Else
      aResultArray = Split(vbNullString, sRowSeparator)
    End If
    
    aFilterArrayByCondition = aResultArray
End Function



Если для вас не является принципиальным - процедура это или функция,
я бы рекомендовал вам преобразовать это в соответствующую процедуру с целью избавления от строки
Код: vbnet
1.
aFilterArrayByCondition = aResultArray
...
Рейтинг: 0 / 0
Функция возвращающая массив - как объявить
    #39571103
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Казанский... делается одной строкой:...
[/src]
как, оказывается, я уже все забыл...
...
Рейтинг: 0 / 0
Функция возвращающая массив - как объявить
    #39574092
Andrey A. Markine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем огромное спасибо за ответы.

[quot Казанский]Andrey A. Markine,

авторВообще, то, что Вы хотите, как я понял, делается одной строкой:
Код: vbnet
1.
2.
3.
Function aFilterArrayByCondition(sInputCSV As String, sCondition As String, sRowSeparator As String) As String()
  aFilterArrayByCondition = Filter(Split(sInputCSV, sRowSeparator), sCondition)
End Function



Этим вы меня вообще убили. Оказалось все так просто. Сейчас использую:
Код: vbnet
1.
2.
aFilterArray = Filter(Split(sPlainTextData, vbNewLine), ":", True)
aFilterArray = Filter(aFilterArray, "_", False)



Правда, не везде прокатило – оказалось что в отчетах с оборудования имеются повторяющиеся строки (например "ОпорМочПуз Дл" и "МочПуз Дл" – убивал бы локализаторов медицинского оборудования).
В связи с чем использовал такую конструкцию, которая фильтрует массив по условиям из справочника до первой совпавшей строки:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
    sFilteredTextData = ""
    Dim bFindString As Boolean
    For iFilterArrayIndex = LBound(aFilterArray, 1) To UBound(aFilterArray, 1)
        bFindString = False
        For iGenRadiologyRefArrayIndex = LBound(aGenRadiologyRefArray, 1) To UBound(aGenRadiologyRefArray, 1)
            If InStr(1, aFilterArray(iFilterArrayIndex), aGenRadiologyRefArray(iGenRadiologyRefArrayIndex, iGenRadPhilipsHD15XE)) _
            And aGenRadiologyRefArray(iGenRadiologyRefArrayIndex, iGenRadPhilipsHD15XE) <> "" And bFindString = False Then
                sFilteredTextData = sFilteredTextData & aFilterArray(iFilterArrayIndex) & vbNewLine
                bFindString = True
            End If
        Next
    Next
    sFilteredTextData = Left(sFilteredTextData, Len(sFilteredTextData) - 1)



Посмотрите если не сложно – может я опять усложняю то что в одну строку делаться?
Заранее спасибо!
...
Рейтинг: 0 / 0
Функция возвращающая массив - как объявить
    #39574146
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrey A. Markine,
Andrey A. MarkineПосмотрите если не сложно – может я опять усложняю то что в одну строку делаться?
Нужно видеть задачу шире, а не теми кусочками, которые вы показываете.

-------------------
по варианту конкретного кода - вам здесь не нужна
Dim bFindString As Boolean

просто замените
bFindString = True
на
Exit For

Когда вам на самом деле понадобится bFindString,
вместо
... And bFindString Then
пишите
If bFindString And ...
Логические выражения вычисляются слева направо
Кроме того, мои вкусовые предпочтения состоят в том, чтобы лепить строку последней операцией:
В данном случае, когда максимальный размер результата у вас определяется размером
фильтрующего массива, схема может выглядеть так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
    sFilteredTextData = ""

    ReDim as_result(LBound(aFilterArray, 1) To UBound(aFilterArray, 1)) As String
  
    Dim i_filtered As Long
    i_filtered = LBound(aFilterArray, 1) - 1&

    For iFilterArrayIndex = LBound(aFilterArray, 1) To UBound(aFilterArray, 1)

        For iGenRadiologyRefArrayIndex = LBound(aGenRadiologyRefArray, 1) To UBound(aGenRadiologyRefArray, 1)

            If Len(aGenRadiologyRefArray(iGenRadiologyRefArrayIndex, iGenRadPhilipsHD15XE)) > 0 _
                    And  InStr(1, aFilterArray(iFilterArrayIndex), aGenRadiologyRefArray(iGenRadiologyRefArrayIndex, iGenRadPhilipsHD15XE)) _
            Then
                  i_filtered = i_filtered + 1& 
                  as_result(i_filtered) = aFilterArray(iFilterArrayIndex)
                Exit For
            End If
        Next
    Next
   
    If i_filtered >= LBound(aFilterArray, 1)  Then
      ReDim Preserve as_result(LBound(aFilterArray, 1) To i_filtered) As String
      sFilteredTextData = Join(as_result, vbNewLine)
    End If
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Функция возвращающая массив - как объявить
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]