Bekerja dengan array di memori VBA dan menghindari loop menggunakan vektorisasi

Saya berpengalaman dalam MATLAB tetapi mendapati diri saya bekerja di VBA akhir-akhir ini karena MATLAB kurang dapat diakses oleh saya dan saya kesulitan mencoba melakukan hal-hal dalam VBA (seperti vektorisasi) yang dapat saya tangani dengan mudah di MATLAB.

Katakanlah saya memiliki tabel data di excel dengan bentuk berikut:

record  startDate   endDate count
1   100 103 10
2   98  102 5
3   101 104 4

Saya ingin melakukan semua pemrosesan saya di memori (menghindari loop) dan kemudian menampilkan file hasil yang terlihat seperti ini:

    1   2   3   Sum
98  0   5   0   5
99  0   5   0   5
100 10  5   0   15
101 10  5   4   19
102 10  5   4   19
103 10  0   4   14
104 0   0   4   4

Pada dasarnya, saya memulai dengan tanggal paling awal dan mengulang tanggal terbaru dan kemudian memeriksa apakah setiap tanggal disertakan dalam jendela tanggal untuk setiap catatan dan jika ya, saya menerapkan jumlah catatan pada hari itu dan kemudian menjumlahkannya.

Saya membuat keluaran yang disertakan menggunakan fungsi lembar kerja sederhana, tetapi saya ingin dapat mereplikasi proses di VBA secara khusus menghindari perulangan, setidaknya mengurangi menjadi 1 perulangan, bukan perulangan yang tertanam.

Jika saya berada di MATLAB saya akan menemukan array logis yang memenuhi suatu kondisi, misalnya:

numDays = 7;
numRecords = 3;
startDate = [100; 98; 101];
endDate = [103; 102; 104];
dateVector = [98; 99; 100; 101; 102; 103; 104];
count = [10; 5; 4];
dateLogic = logical(numDays,numRecords);
for d = 1:numDays
  dateLogic(d,:) = dateVector(d) >= startDate(:,1) &  dateVector(d) <= endDate(:,1)
end
countMatrix = dateLogix * count';
Sum = sum(countMatrix,2);

Ini akan memberi saya matriks logis dari nol dan satu yang dapat saya kalikan silang dengan vektor hitungan untuk mendapatkan jumlah saya dan akhirnya vektor Jumlah saya. Saya yakin saya bahkan bisa menggunakan bsxfun untuk menghapus loop pada hari-hari tertentu.

Mohon maafkan potensi kesalahan sintaksis karena saya tidak memiliki akses ke MATLAB saat ini.

Lagi pula, bagaimana saya bisa melakukan hal serupa di VBA. Apakah ada notasi titik dua yang setara untuk mereferensikan seluruh rentang kolom atau baris dalam array. Saya akan menerapkan kumpulan data yang besar sehingga efisiensi adalah yang terpenting. Semakin banyak yang bisa saya lakukan dalam memori sebelum menempelkannya, semakin baik.

Terima kasih sebelumnya.


person Keith D    schedule 23.07.2014    source sumber
comment
Anda harus menggunakan beberapa fungsi khusus untuk mengiris array. Dengan array matriks 2d, cukup mudah untuk membuat fungsi GetRow atau fungsi GetColumn. Ada juga banyak fungsi pembantu yang berguna di sini: www.cpearson.com/excel/array.htm   -  person David Zemens    schedule 24.07.2014
comment
Dua petunjuk bagus, meskipun saya ingin menghindari mempelajari bahasa lain (Oktaf). Fungsi array pada tautan yang disediakan berpotensi mendukung apa yang saya butuhkan.   -  person Keith D    schedule 24.07.2014


Jawaban (1)


Inilah satu kemungkinan, coba dengan sampe data di A1:A4 buku kerja baru.

Sub NewTable()

Set Table = Sheet1.[a2:d4]

With Application

    Record = .Transpose(.Index(Table, , 1))
    FirstDate = .Transpose(.Index(Table, , 2))
    LastDate = .Transpose(.Index(Table, , 3))
    Count = .Transpose(.Index(Table, , 4))

    Dates = .Evaluate("row(" & .Min(FirstDate) & ":" & .Max(LastDate) & ")")
    Values = .PV(, Count, .PV(, .GeStep(Dates, FirstDate), .GeStep(LastDate, Dates)))
    Sum = .MMult(Values, .Power(.Transpose(Record), 0))

End With

Sheet1.[F1].Offset(, 1).Resize(, UBound(Values, 2)) = Record
Sheet1.[F2].Resize(UBound(Dates)) = Dates
Sheet1.[G2].Resize(UBound(Values), UBound(Values, 2)) = Values
Sheet1.[G2].Offset(, UBound(Values, 2)).Resize(UBound(Dates)) = Sum

End Sub
person lori_m    schedule 04.09.2014