2013-05-17 27 views
12

Pracuję z VBA. Napisałem funkcję definiującą użytkownika, która pobiera string, przetwarza ją i zwraca oczyszczoną string. Nie jestem pewien, co jest z tym nie tak. Nie jestem w stanie go wywołać i poprosić o przetworzenie ciągu znaków i zwrócenie go. Myślę, że jest błąd w sposobie definiowania lub zwracania go.Niedopasowanie argumentu ByRef w programie Excel VBA

Public Function ProcessString(input_string As String) As String 
    ' The temp string used throughout the function 
    Dim temp_string As String 

    For i = 1 To Len(input_string) 
     temp_string = Mid(input_string, i, 1) 
     If temp_string Like "[A-Z, a-z, 0-9, :, -]" Then 
      return_string = return_string & temp_string 
     End If 
    Next i 
    return_string = Mid(return_string, 1, (Len(return_string) - 1)) 
    ProcessString = return_string & ", " 
End Function 

I korzystać z tej funkcji jak ten

Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name) 

Nazwisko jest zmienną ciąg, zwykle wygląda to Lastname*****, a ja staram się usunąć wszystkie gwiazdy za nim. Czy to powróci Lastname bez gwiazdek.

Otrzymałem Compile error: ByRef arugment type mismatch kiedy próbowałem to uruchomić. Używam systemu Windows XP z pakietem Office 2003.

EDYCJA: Dodałem podstawową strukturę kodu, który posiadam, mam około 20 linii podobnego kodu. Robię to samo dla każdego pola, którego potrzebuję.

Private Sub CommandButton2_Click() 
' In my original production code I have a chain of these 
' Like this Dim last_name, first_name, street, apt, city, state, zip As String 
Dim last_name As String 

' I get the last name from a fixed position of my file. Because I am 
' processing it from another source which I copied and pasted into excel 
last_name = Mid(Range("A4").Value, 20, 13) 

' Insert the data into the corresponding fields in the database worksheet 
Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name) 
+3

Na której linii znajduje się erro r flaga? – Gaffi

+0

Spadł na linii, kiedy ja to nazywam. 'Arkusze robocze (arkusz_danych) .Range (" C2 ") Wartość = ProcessString (last_name)' – George

Odpowiedz

29

Podejrzewam, że nie skonfigurowałeś prawidłowo last_name w telefonie wywołującym.

ze stwierdzeniem Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)

to będzie działać tylko wtedy, gdy last_name jest ciągiem znaków, tj

Dim last_name as String 

rozmówcy pojawia się gdzieś.

Powodem tego jest to, że VBA przekazuje zmienne przez odniesienie domyślnie, co oznacza, że ​​typy danych muszą dokładnie odpowiadać między dzwoniącym a wywoływanym.

Dwie poprawki:

1) zmienić funkcję Public Function ProcessString(ByVal input_string As String) As String

2) umieścić Dim last_name As String w wywołującego przed użyciem.

(1) działa, ponieważ dla ByVal kopia input_string jest pobierana podczas przekazywania do funkcji, która zamieni ją na poprawny typ danych. Prowadzi to również do lepszej stabilności programu, ponieważ funkcja nie może modyfikować zmiennej w wywołującym.

+0

Dziękujemy! Dodanie 'ByVal' naprawiło problem, teraz kod działa poprawnie! – George

+1

Zawsze deklaruję wszystkie moje funkcje VBA z ByVal, ponieważ poprawia to stabilność. Z Javą nie masz wyboru, wszystko jest przekazywane przez wartość. – Bathsheba

2

Podczas gdy przechodzenie przez ciąg znaków jednej litery na raz jest metodą opłacalną, nie ma takiej potrzeby. VBA posiada wbudowane funkcje dla tego typu rzeczy:

Public Function ProcessString(input_string As String) As String 
    ProcessString=Replace(input_string,"*","") 
End Function 
+0

To naprawdę dobre rozwiązanie. Ale czy mógłbyś mi pokazać, jak rozwiązać problem? Ponieważ próbuję również dowiedzieć się, co zrobiłem źle. Dziękuję Ci! – George

3

zmieniłem kilka rzeczy do pracy z Option Explicit, a kod pobiegł w porządku wobec komórki zawierającej "abc.123", który powrócił "abc.12,". Nie wystąpiły błędy kompilacji.

Option Explicit ' This is new 

Public Function ProcessString(input_string As String) As String 
    ' The temp string used throughout the function 
    Dim temp_string As String 
    Dim i As Integer ' This is new 
    Dim return_string As String ' This is new 
    For i = 1 To Len(input_string) 
     temp_string = Mid(input_string, i, 1) 
     If temp_string Like "[A-Z, a-z, 0-9, :, -]" Then 
      return_string = return_string & temp_string 
     End If 
    Next i 
    return_string = Mid(return_string, 1, (Len(return_string) - 1)) 
    ProcessString = return_string & ", " 
End Function 

Zasugeruję, aby opublikować więcej odpowiedniego kodu (który wywołuje tę funkcję). Stwierdziłeś, że last_name to ciąg znaków, ale wydaje się, że tak nie jest. Przejdź przez linię kodu po linii i upewnij się, że tak właśnie jest.

+0

Po dodaniu pominiętej instrukcji Dim, wyświetliłem monit (podświetlono) linię, w której mam 'Private Sub CommandButton2_Click()', a także 'last_name' jest podświetlona. Bardzo dziwne zachowania, mój Sub jest w zasadzie buttom, który robi listę rzeczy. – George

+0

Dzięki za wskazanie pominiętej instrukcji Dim! – George

5

Nie wiem dlaczego, ale bardzo ważne jest, aby zadeklarować zmienne osobno, jeśli chcesz przekazać zmienne (jako zmienne) do innej procedury lub funkcji.

Na przykład istnieje procedura, która powoduje pewną manipulację danymi: na podstawie ID zwraca numer części i informacje o ilości. ID jako wartość stała, pozostałe dwa argumenty to zmienne.

Public Sub GetPNQty(ByVal ID As String, PartNumber As String, Quantity As Long) 

następny kod główny daje mi "ByRef niedopasowanie argument":

Sub KittingScan() 
Dim BoxPN As String 
Dim BoxQty, BoxKitQty As Long 

    Call GetPNQty(InputBox("Enter ID:"), BoxPN, BoxQty) 

End sub 

i następny pracuje także:

Sub KittingScan() 
Dim BoxPN As String 
Dim BoxQty As Long 
Dim BoxKitQty As Long 

    Call GetPNQty(InputBox("Enter ID:"), BoxPN, BoxQty) 

End sub 
+1

Tak, to był mój problem. VBA - tak mylące. Musi być, ponieważ jest "dostępny". – Eric

+0

Traciłem rozum, nie mogę uwierzyć, że tego potrzebowałem, dziękuję. –

0

Coś jest nie tak z tym ciągiem spróbować tak:

Worksheets(data_sheet).Range("C2").Value = ProcessString(CStr(last_name)) 
Powiązane problemy