2017-09-16 18 views
0

任務Excel的VBA - 避免錯誤1004寫入UF列表框陣列到鈑

我的目的是寫回用戶窗體列表框數據到片材的範圍中使用所述數據字段方法的最有效方式。

爲了將數據寫入到一個範圍的基本方法(特別是使用的數據範圍)

AFAIK最有效的方法是使用陣列。如果數據來源於一個範圍,則最好使用數據字段數組,默認情況下是二維的(一個基於數組),並允許 a)從數據表獲取數據或 b)將數組寫回 與一個碼行:使用列表框數據陣列

列表框數據被存儲在一個2dim時

Dim v ' As Variant 
Dim rng As Range 
Set rng = ... 

' a) range to array 
     v = rng.Value 

' b) array to range 
    rng.Value = v 

差異,但零基於陣列,例如ListBox1.List

[提示:因此可以使用預定義的數組來創建項目,而不是使用通常所知的Add方法,BTW僅限於10列(索引0到9)。 ]

儘管這種差異,可以在列表框數據讀取,並將其與所描述的基本方法寫回到片:

' aa) ListBox data to array 
    v = Me.ListBox1.List 

' bb) array to range 
rng.Value = v 

此外,我指出,通過默認的陣列列數10,所以這不會對應於以編程方式設置的ColumnCount。因此,有必要調整檢查數組維度的範圍,參見參考資料。代碼示例中的調試協議。

問題和解決

寫回數據字段陣列片在一個襯裏引發錯誤1004(應用程序定義或對象定義的錯誤)如果有與物品的主要「==」字符串或可比較的用戶輸入,因爲這不能由Excel正確解釋。

我使用

rng.Text = v 

代替

rng.value = v 

企圖沒有失敗,也造成了424對象所需的錯誤。

問題 ==>是否有可能以解決導致潛在的誤差項「=」字符不用循環通過使用VBA或API方法的所有數組項?任何代碼的例子是歡迎各地(步驟3中的代碼)

我的代碼

我的代碼包括四個步驟 1)創建2dim數據字段陣列(ⅴ) 2)集合代替我的工作的目標範圍(RNG) 3)[我的工作圍繞校正每個數組項] 4)將數據寫回工作表

Private Sub CommandButton1_Click() 
' declare variables 
    Dim ws As Worksheet 
    Set ws = ThisWorkbook.Worksheets("Dump") 

    Dim s  As String    ' range address string 
    Dim sTest As String    ' item test string 
    Dim v  As Variant   ' data field array 
    Dim rng As Range    ' (target) range 
    Dim i  As Long    ' rows counter 
    Dim j  As Long    ' columns counter 
    Dim R  As Long    ' number of rows 
    Dim C  As Integer   ' number of columns 
    Dim lbxR As Long    ' actual number of listbox items in data field 
    Dim lbxC As Integer   ' actual number of listbox columns in data field 
' Error Handler 
    On Error GoTo OOPS 

' get programmatically defined listbox dimension 
    R = Me.ListBox1.ListCount 
    C = Me.ListBox1.ColumnCount 
' clear sheet lines A2:A{r} 
    ws.Range(Cells(2, 1), Cells(R, C)).value = "" 
' =============================== 
' 1) create 2dim data field array 
' ------------------------------- 
    v = Me.ListBox1.List 

' ------------------------------- 
' 2) set target range (rng) 
' ------------------------------- 
' get actual data field dimension 
    lbxR = UBound(v, 1) - LBound(v, 1) + 1 ' first dimension 
    lbxC = UBound(v, 2) - LBound(v, 2) + 1 ' second dimension 
    s = ws.Range("A2").Resize(lbxR, lbxC).Address 
' set correconding target range 
    Set rng = ws.Range(s)       ' target range 

' create short protocol - columns by default differ from user defined ColumnCount property ! 
    Debug.Print String(80, "-") 
    Debug.Print vbNewLine & "** ListBox1 Defs   Data Field Array Dimension **" 
    Debug.Print "       [Target Range " & s & "]" 
    Debug.Print String(80, "-") 
    Debug.Print " ListCount = " & ListBox1.ListCount, "rows = " & lbxR & " = ubound(v,1)-lbound(v,1)+1 = " & UBound(v, 1) & " - " & LBound(v, 1) & " + 1 " 
    Debug.Print " ColumnCount= " & ListBox1.ColumnCount, "cols = " & lbxC & " = ubound(v,2)-lbound(v,2)+1 = " & UBound(v, 2) & " - " & LBound(v, 2) & " + 1 " 
    Debug.Print String(80, "-") 

' ---------------------------------------------------------------- 
' 3) Work around - correct leading "=", if any occurences presumed 
' (avoid error 1004 - App-defined or object-defined error) 
' ---------------------------------------------------------------- 
' ==> Is there an alternative way? 
' For i = 0 To R - 1   ' edited thx to D.Lee 
' For j = 0 To C - 1 
'  v(i, j) = IIf(Left(Me.ListBox1.List(i, j) & "", 1) = "=", " ", "") & _ 
'       Me.ListBox1.List(i, j) 
' Next j 
' Next i  
' ------------------------------- 
' 4) write data back to worksheet 
' ------------------------------- 
    rng.value = v 

Exit Sub 

' ============= 
' Error Handler 
' ============= 
OOPS: 
    MsgBox "ERL=" & Erl & " |Error " & Err.Number & "|" & Err.Description & vbNewLine & _ 
     "s=" & s, vbExclamation 

End Sub 

提示建議閱讀"Arrays and Ranges in VBA" by C.Pearson

+0

基本上我認爲這個版本包括步驟3)對我來說是滿意的。拆分和加入交易將無助於避免循環。由於我在API manoever領域並不堅定,我認爲他們風險太大;不過如果CopyMemory有可能使用,我會很高興有一些提示。對我來說最有趣的是,無論如何,從ListBox1.List讀入的數組都由TENcolumns組成。 –

+0

**提示:**對於那些對使用OS API感興趣的人,我建議您閱讀@ Florent-B的智能解決方案,如何直接在內存中移動列;看到https://stackoverflow.com/questions/46712110/how-to-add-a-counter-column-to-existing-matrix-in-vba/46786604#46786604 –

回答

1

因爲需要修改i和j,所以需要修改(v,1)= 0 ubound(v,1)= r-。

For i = 0 To R - 1 
     For j = 0 To C - 1 
     v(i, j) = IIf(Left(Me.ListBox1.List(i, j) & "", 1) = "=", " ", "") & _ 
          Me.ListBox1.List(i, j) 
     Next j 
    Next i 
+0

我欣賞你的幫助提示+,但我原來的工作沒問題。你當然是對的。我匆匆趕走了錯誤的數字。我會編輯我的問題:-)然而,我的希望是找到一種替代的直接方式,而不需要通過數組的額外循環。 –