การทำงานกับอาร์เรย์ในหน่วยความจำ VBA และการหลีกเลี่ยงการวนซ้ำโดยใช้เวกเตอร์

ฉันคุ้นเคยกับ MATLAB แต่พบว่าตัวเองทำงานใน VBA ทุกวันนี้ เนื่องจากฉันเข้าถึง MATLAB ได้น้อยกว่า และฉันต้องดิ้นรนกับการพยายามทำสิ่งต่าง ๆ ใน VBA (เช่น การทำเวกเตอร์) ที่ฉันสามารถจัดการได้อย่างง่ายดายใน MATLAB

สมมติว่าฉันมีตารางข้อมูลใน Excel ในรูปแบบต่อไปนี้:

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

ฉันต้องการประมวลผลทั้งหมดในหน่วยความจำ (หลีกเลี่ยงการวนซ้ำ) จากนั้นจึงส่งออกไฟล์ผลลัพธ์ที่มีลักษณะดังนี้:

    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

โดยพื้นฐานแล้ว ฉันเริ่มต้นด้วยวันที่แรกสุดและวนซ้ำวันที่ล่าสุด จากนั้นตรวจสอบว่าแต่ละวันที่รวมอยู่ในหน้าต่างวันที่สำหรับแต่ละเรกคอร์ดหรือไม่ และหากเป็นเช่นนั้น ฉันจะใช้การนับเรกคอร์ดกับวันนั้นแล้วสรุปผล

ฉันสร้างเอาต์พุตที่รวมไว้โดยใช้ฟังก์ชันเวิร์กชีทแบบง่าย แต่ฉันต้องการที่จะทำซ้ำกระบวนการใน VBA โดยเฉพาะโดยหลีกเลี่ยงการวนซ้ำอย่างน้อยเหลือ 1 ลูปแทนที่จะเป็นลูปแบบฝัง

ถ้าฉันอยู่ใน MATLAB ฉันจะค้นหาอาร์เรย์แบบลอจิคัลที่ตรงตามเงื่อนไข เช่น:

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);

นี่จะให้เมทริกซ์เชิงตรรกะของศูนย์และเมทริกซ์ที่ฉันสามารถข้ามคูณกับเวกเตอร์นับเพื่อให้ได้จำนวนนับและสุดท้ายเวกเตอร์ผลรวมของฉัน ฉันเชื่อว่าฉันสามารถใช้ bsxfun เพื่อลบการวนซ้ำในหลายวันได้

โปรดแก้ตัวข้อผิดพลาดทางไวยากรณ์ที่อาจเกิดขึ้น เนื่องจากฉันไม่สามารถเข้าถึง MATLAB ได้ในขณะนี้

อย่างไรก็ตาม ฉันจะทำสิ่งที่คล้ายกันใน VBA ได้อย่างไร มีเครื่องหมายโคลอนที่เทียบเท่าในการอ้างอิงช่วงคอลัมน์หรือแถวทั้งหมดในอาร์เรย์หรือไม่ ฉันจะนำไปใช้กับชุดข้อมูลขนาดใหญ่ ดังนั้นประสิทธิภาพจึงเป็นสิ่งสำคัญ ยิ่งทำในความทรงจำก่อนแปะได้มากเท่าไหร่ก็ยิ่งดีเท่านั้น

ขอบคุณล่วงหน้า.


person Keith D    schedule 23.07.2014    source แหล่งที่มา
comment
คุณจะต้องใช้ฟังก์ชันที่กำหนดเองเพื่อแบ่งอาร์เรย์ ด้วยอาร์เรย์เมทริกซ์ 2d การสร้างฟังก์ชัน GetRow หรือฟังก์ชัน GetColumn ค่อนข้างง่าย นอกจากนี้ยังมีฟังก์ชันตัวช่วยที่มีประโยชน์มากมายที่นี่: www.cpearson.com/excel/array.htm   -  person David Zemens    schedule 24.07.2014
comment
โอกาสในการขายที่ดีสองครั้ง แม้ว่าฉันต้องการหลีกเลี่ยงการเรียนรู้ภาษาอื่น (อ็อกเทฟ) ฟังก์ชันอาร์เรย์บนลิงก์ที่ให้มามีศักยภาพที่จะสนับสนุนสิ่งที่ฉันต้องการ   -  person Keith D    schedule 24.07.2014


คำตอบ (1)


มีความเป็นไปได้อย่างหนึ่ง ให้ลองใช้ข้อมูลตัวอย่างใน A1:A4 ของสมุดงานใหม่

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