Небольшая функция для изменения массива строк в VBA

Я писал макрос для Solidworks в VBA, и в какой-то момент я хотел бы переставить листы на чертеже следующим образом: если какой-либо из листов называется «CUT», переместите этот лист на передний план. . API Solidworks предоставляет способ переупорядочить листы, но для этого требуется массив имен листов, отсортированных в правильном порядке - достаточно справедливо. Способ получения имен листов выглядит следующим образом: метод.

Итак, я попытался написать небольшую функцию для перестановки листов так, как я хочу. Вызов функции, которую я пытаюсь использовать, и функция показаны здесь

Вызов функции

Dim swApp           As SldWorks.SldWorks
Dim swDrawing       As SldWorks.DrawingDoc
Dim bool            As Boolean

Set swApp = Application.SldWorks
Set swDrawing = swApp.ActiveDoc

.
.
.

bool = swDrawing.ReorderSheets(bringToFront(swDrawing.GetSheetNames, "CUT"))

Определение функции

Private Function bringToFront(inputArray() As String, _
    stringToFind As String) As String()

Dim i               As Integer
Dim j               As Integer
Dim first           As Integer
Dim last            As Integer
Dim outputArray()   As String

first = LBound(inputArray)
last = UBound(inputArray)

ReDim outputArray(first to last)

For i = first To last
    If inputArray(i) = stringToFind Then
        For j = first To (i - 1)
            outputArray(j + 1) = inputArray(j)
        Next j
        For j = (i + 1) To last
            outputArray(j) = inputArray(j)
        Next j
        outputArray(first) = stringToFind
    End If
Next i

bringToFront = outputArray

End Function

Я получаю сообщение об ошибке: «Несоответствие типов: ожидается массив или пользовательский тип» в строке вызова функции. Я провел немало поисков и думаю, что то, что я испортил, связано со статическими и динамическими массивами, но я не смог найти решение самостоятельно.


person JDP    schedule 27.09.2015    source источник
comment
Это, вероятно, не решит вашу проблему, но вы определенно должны ReDim bringToFront(first to last), иначе ваш код не будет работать, если inputArray не отсчитывается от нуля. Это все, что я мог увидеть подозрительного в вашем коде.   -  person A.S.H    schedule 28.09.2015
comment
Кстати, почему бы вам просто не использовать Sheets("CUT").Move before:=Sheets(1)? Вы можете проверить, существуют ли Sheets(CUT). или просто используйте Возобновить при ошибке   -  person A.S.H    schedule 28.09.2015
comment
Спасибо за вашу помощь! Я попробую ваше предложение, но просмотрев sheet, я не вижу Move среди них. Я что-то упускаю?   -  person JDP    schedule 28.09.2015
comment
Move является членом класса Worksheet. Это будет работать ;), даже если Intellisense не предлагает (часто бывает с такими вызовами).   -  person A.S.H    schedule 28.09.2015
comment
Чтобы было ясно, это не объект листа Excel, а объект листа Solidworks. К сожалению, я не могу заставить его делать что-либо, кроме ошибки с помощью метода .Move.   -  person JDP    schedule 28.09.2015
comment
Я предлагаю отредактировать свой пост, исправить оператор Redim и явно показать оператор вызова и где он ломается.   -  person A.S.H    schedule 28.09.2015
comment
Ну, что ж, спасибо. Я до сих пор не вижу места, где вы называете BringToFront. Может быть, вы должны swDrawing.ReorderSheets(BringToFront(swDrawing.GetSheetNames), "CUT"). О, я вижу, есть еще одна проблема, это может быть она.   -  person A.S.H    schedule 28.09.2015
comment
Упс, ты прав! Извините за это, на самом деле это то, что у меня было изначально, но я играл с вызовом функции, прежде чем публиковать здесь. Я исправлю звонок. Спасибо еще раз за помощь!   -  person JDP    schedule 28.09.2015
comment
Этот bringToFront(j + 1) = inputArray(j) слишком похож на вызов функции для левой части присваивания. Обычно вы можете использовать локальную переменную для retval вместо этого без потери производительности, особенно. если последняя строка bringToFront = retVal, копирование массива не происходит (только возня с указателем).   -  person wqw    schedule 28.09.2015
comment
@wqw да, это была проблема с генерацией сообщения об ошибке, как указано в моем ответе   -  person A.S.H    schedule 28.09.2015
comment
@JDP, пожалуйста, смотрите мой ответ ниже для проблемы, которая фактически вызвала сообщение об ошибке, и проверенное исправление. Надеюсь, это помогло :)   -  person A.S.H    schedule 28.09.2015


Ответы (1)


Помимо исправлений, предложенных в комментариях, происходит то, что в строках

bringToFront(j + 1) = inputArray(j)

и

bringToFront(first) = stringToFind

компилятор считает, что вы пытаетесь рекурсивно вызвать функцию BringToFront. Вот почему он жалуется на количество параметров в сообщении об ошибке. Чтобы исправить это, просто создайте другой массив как локальную переменную массива с другим именем, давайте назовем его «ret», заполните его соответствующим образом и назначьте его в конце перед возвратом.

РЕДАКТИРОВАТЬ: Кроме того, лучше объявить массивы как типы Variant, чтобы избежать проблем совместимости между VB6 и .Net. Это был последний выпуск

Private Function bringToFront(inputArray As Variant, _
stringToFind As String) As Variant

    Dim i       As Integer
    Dim j       As Integer
    Dim first   As Integer
    Dim last    As Integer

    first = LBound(inputArray)
    last = UBound(inputArray)

    Dim ret() As String
    ReDim ret(first To last)

    For i = first To last
        If inputArray(i) = stringToFind Then
            For j = first To (i - 1)
                ret(j + 1) = inputArray(j)
            Next j
            ret(first) = stringToFind
        End If
    Next i
    bringToFront = ret
End Function
person A.S.H    schedule 27.09.2015
comment
Это имеет большой смысл. Я исправил функцию в исходном вопросе в соответствии с вашими предложениями здесь. К сожалению, я все еще получаю ошибку о несоответствии типов, когда пытаюсь вызвать функцию. - person JDP; 28.09.2015
comment
Вы изменили имя переменной, как это было предложено в исправлении? - person A.S.H; 28.09.2015
comment
@JDP Если вы это сделали, похоже, нам нужно увидеть сигнатуру функции swDrawing.ReorderSheets, а также объявление переменной bool! - person A.S.H; 28.09.2015
comment
Я включил определение bool, но я не совсем уверен, что вы подразумеваете под сигнатурой swDrawing.ReorderSheets. Это — это страница в руководстве по API. Это то, что вам нужно? Спасибо еще раз. - person JDP; 28.09.2015
comment
@JDP кажется, это проблема сортировки между VB6 и VB.Net. Нужно попробовать использовать Variants вместо массивов (см. отредактированную версию сигнатуры BringToFront), и определить, где именно проблема, я имею в виду при переходе с .net на vb6 или наоборот. Разобьем вызов на два вызова: dim newOrder as Variant, newOrder = BringToFront(...), затем вызов ReoderSheets(newOrder) - person A.S.H; 28.09.2015
comment
Бинго, достаточно было просто изменить определение на Variant, чтобы получить ожидаемое поведение. Думаю, сегодня вечером у меня закончилось чтение, чтобы понять, что такое Варианты. - person JDP; 28.09.2015
comment
Большой! так что это действительно была проблема совместимости. Я заподозрил это, когда увидел объявление reorderSheets в руководстве sldWorks. В заключение я думаю, что мы всегда должны использовать варианты вместо явных массивов при взаимодействии между VB6 и .Net. :) - person A.S.H; 28.09.2015