2016-05-13 32 views
1

我當前讀取的2維範圍到Excel VBA陣列像這樣:計數數

Set Ws = Sheet1 
Ws.Activate 

LastRow = Ws.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row 
LastCol = Ws.Cells.Find("*", searchorder:=xlByColumns, searchdirection:=xlPrevious).Column 

ReDim elements(0 To LastRow - 2, 0 To LastCol - 2) 
elements = Ws.Range(Cells(2, 1), Cells(LastRow, LastCol)) 

範圍是25行乘11列。但是,並非該範圍內的所有單元格都具有值,因此數組中的某些值爲「空」。

  • 山口A具有25項
  • 列B具有16
  • COL K具有12 ...

我通過這個陣列需要循環和創建的第二陣列,這將是一個「笛卡爾產品」的值從第一個。爲了確定我需要循環多少次,我需要弄清楚每個數組列中有多少項(「維度」?)。

這裏是我的循環的嘗試:

Row = 0 

For i = 1 To 25 'numElements in column 1 
For j = 1 To 3 'numElements in column 6   
    For k = 1 To 5 'numElements in column 7 
    For l = 1 To 14 'numElements in column 8 
    For m = 1 To 6  'numElements in column 10 
    For n = 1 To 12  'numElements in column 11 

     cartesian(Row, 0) = elements(i, 0) 
     cartesian(Row, 1) = elements(i, 1) 
     cartesian(Row, 2) = elements(i, 2) 
     cartesian(Row, 3) = elements(i, 3) 
     cartesian(Row, 4) = elements(i, 4) 
     cartesian(Row, 5) = elements(j, 5) 
     cartesian(Row, 6) = elements(k, 6) 
     cartesian(Row, 7) = elements(l, 7) 
     cartesian(Row, 8) = elements(l, 8) 
     cartesian(Row, 9) = elements(m, 9) 
     cartesian(Row, 10) = elements(n, 10) 

     Row = Row + 1 
    Next n   
    Next m 
    Next l 
    Next k 
Next j 
Next i 

任何幫助表示讚賞:)

編輯1:

這是我讀入陣列1的範圍內:

Austria sem jan 
Belgium gdn feb 
France  mar 
US   apr 
       may 
       jun 

我需要能夠統計多少「項目「在第1欄,第2欄和第3欄中以便將它們相乘。這樣我會知道我需要多大的ReDim第二陣列。

這是我所需要的陣列2和最後寫回另一片:

Austria sem jan 
Austria sem feb 
Austria sem mar 
Austria sem apr 
Austria sem may 
Austria sem jun 
Austria gdn jan 
Austria gdn feb 
Austria gdn mar 
Austria gdn apr 
Austria gdn may 
Austria gdn jun 
Belgium sem jan 
Belgium sem feb 
Belgium sem mar 
Belgium sem apr 
Belgium sem may 
Belgium sem jun 
Belgium gdn jan 
Belgium gdn feb 
Belgium gdn mar 
Belgium gdn apr 
Belgium gdn may 
Belgium gdn jun 

+0

我認爲這可能會超過它。你的目標是什麼?在一個範圍內找到空的細胞?那麼,對於第1,6,7,8,10和11列,你想要找到空單元格? – BruceWayne

+1

或者Alex只想將第2列至第11列的「非空」值與第1列的值相結合? – Kellsens

+0

我也不明白它......去*笛卡爾積*但沒有計算......它只是第一個範圍的副本(只是值被混洗)。那麼開始時有什麼不同?每一行?但有n套也提供了一個n維輸出...我很困惑:/ –

回答

1

像你需要它的時候一個像樣的量這應該這樣做。 ..還需要一段時間〜300K的條目:

Option Explicit 

Sub getMyList() 

    'set input 
    Dim inputVal As Variant 

    'get input values 
    With ThisWorkbook.Worksheets("Sheet1") 
    inputVal = .Range(.Cells(1, 1), .Cells(.Cells.Find("*", , , , 1, 2).Row, .Cells(1, 1).End(xlToRight).Column)).Value 
    End With 

    'set count array 
    Dim xCounts() As Variant 
    ReDim xCounts(1 To UBound(inputVal, 2)) 

    Dim i As Long, j As Long 
    For i = 1 To UBound(xCounts) 
    j = 1 
    While inputVal(j, i) <> "" And j < UBound(inputVal) 
     j = j + 1 
    Wend 
    'xCounts(i) = j - 1 'will skip last value if it is at the last row 
    xCounts(i) = j + (inputVal(j, i) = "") 'new one will work as wanted 
    Next 

    'set output sizes 
    Dim outVal() As Variant 
    ReDim outVal(1 To Application.Product(xCounts), 1 To UBound(xCounts)) 

    'runner sets 
    Dim colRunner As Long, rowRunner As Long, copyRunner As Long 
    Dim itemRep As Long, listRep As Long 

    For colRunner = 1 To UBound(xCounts) 

    rowRunner = 1 
    itemRep = 1 
    listRep = 1 

    'repeat whole list 
    For i = 1 To colRunner - 1 
     listRep = listRep * xCounts(i) 
    Next 

    'repeat each item 
    For i = colRunner + 1 To UBound(xCounts) 
     itemRep = itemRep * xCounts(i) 
    Next 

    'run the list for output 
    copyRunner = 1 
    For i = 1 To listRep 
     For copyRunner = 1 To xCounts(colRunner) 
     For j = 1 To itemRep 

      outVal(rowRunner, colRunner) = inputVal(copyRunner, colRunner) 
      rowRunner = rowRunner + 1 

     Next 
     Next 
    Next 
    Next 

    'output everything 
    ThisWorkbook.Worksheets("Sheet2").Cells(1, 1).Resize(UBound(outVal), UBound(outVal, 2)).Value = outVal 

End Sub 

的代碼應該很容易閱讀(裏面有沒有真正的魔法):P

但是,如果任何問題都離開了,只問:)

編輯

xCounter只需持有的所有項目每列的計數,因爲這個數字是用很多次。
對於澄清:讓我們假設你有一個這樣的名單:

A B C D E 
1 1 1 1 1 
2 2 2 2 2 
3 3 3 3 
4 4 4 
5 5 5 
6 6 6 
7  7 
8 

(爲了便於計數使用的號碼,也與任何字符串作品)
xCounter現在將{8,2,6,7,3}。現在,如果你想寫下欄C,那麼你需要知道每個項目需要重複多少次。這可以通過乘以後面所有列的計數來計算。對於這種情況,它將是7 * 3 = 21次。此外,您需要知道列表中有多少項要循環,其中將是6。然後整個列表也需要重複,可以通過乘以它前面所有行的計數來計算。那將是8 * 2 = 16次。這種方式也建立了3個內部For ... Next循環。 ListRepeat(EachItem(ItemRepeat))。 要知道輸出數組中的哪一行將被寫入,您需要一個簡單的遞增計數值,即RowCounter。直接在表單中執行此操作時,每次將值寫入單元格時,都會使用一個範圍,該範圍只是將一行向下偏移。
通過這個系統,您可以將每個列與其他列完全分開,因爲您需要的只是前面和後面列(我們有xCounter)的項目計數的結果。我們仍然需要爲每列執行此操作,以便外循環是列(colRunner)。
只是爲了不讓人感到困惑,因爲在內部使用i, j, k, l 4個循環,我將outValrowRunner中的行以及列中的行重命名爲。有重複的上限和下限直接設置在內圈前,我留在ij。 (他們不用於任何環路中的任何事物,他們只需通過多次執行相同的動作就可以確保重複)

如果我錯過了某些或其他問題,請執行此操作,因爲它始終是正確的做:問。 ;)

+0

我喜歡你這樣做的方式(我想的是一種不同的方式,但可能不是那麼好)。我注意到的一件事是它跳過最後一列中的'jun' - 建議類似於For j = 1 To UBound(inputVal) 如果inputVal(j,i)=「」則退出 接下來的j在set count數組代碼中。 –

+1

@TomSharpe將'xCounts(i)= j - 1'改爲'xCounts(i)= j +(inputVal(j,i)=「」)'。應該現在工作:) –

+0

德克,謝謝你的巨大努力,我真的很感激它!這裏[link](http://jsfiddle.net/astrbac/vj1atc82)是我如何「調整」它到我的風格(頂部的聲明)。然而,我在理解方面掙扎了一下:你首先創建一個要組合的數組。最後你創建一個數組來回寫表單。但是我不明白是什麼xCount數組和rowRunner和colRunner做了什麼?非常感謝提前發球! –