Board logo

標題: [發問] 陣列的值放置到excel的問題 [打印本頁]

作者: PKKO    時間: 2015-6-21 14:36     標題: 陣列的值放置到excel的問題

RNG=[A5].CURRENTREGION'假設UBOUND(RNG)=20 ,UBOUND(RNG,2)=10
Q1 : [A1].Resize(20, 10).Value =RNG'我覺得這是將陣列資料放在excel非常快的方式,不曉得還有更快的嬤?
Q2 : 如果RNG這個陣列,我希望它由RNG(2 TO 16,3 TO 5) 放到 [A1].Resize(15, 3).Value這裡面該如何做?因為目前Q1程式碼無法達成這種放置方式
PS:有沒有答案不是迴圈的.CELLS(x,x)=RNG(X,X)的方式
作者: GBKEE    時間: 2015-6-21 15:20

回復 1# PKKO
試試看
  1. Option Explicit
  2. Sub EX()
  3.     Dim Rng()
  4.     With Range("D1").CurrentRegion
  5.         Rng = .Cells(2, 3).Resize(15, 3).Value
  6.     End With
  7.     [A1].Resize(15, 3) = Rng
  8. End Sub
複製代碼

作者: lpk187    時間: 2015-6-21 16:19

本帖最後由 lpk187 於 2015-6-21 16:22 編輯

回復 2# GBKEE


   我想PKKO大大的意思是有個Rng(1 to 20,1 to 10)的陣列
但他只取RNG(2 TO 16,3 TO 5)範圍的值,可有辦法不用任何迴圈
就可以直接取出的意思
作者: GBKEE    時間: 2015-6-21 16:23

回復 3# lpk187
只取RNG(2 TO 16,3 TO 5),可有辦法不用for...next

這不是不用迴圈?
  1. With Range("D1").CurrentRegion
  2.        Rng = .Cells(2, 3).Resize(15, 3).Value
  3.     End With
複製代碼

作者: lpk187    時間: 2015-6-21 16:33

本帖最後由 lpk187 於 2015-6-21 16:34 編輯

回復 4# GBKEE


  PKKO的意思是Rng(1 to 20,1 to 10)已經有值了,不是再去取
With Range("D1").CurrentRegion
       Rng = .Cells(2, 3).Resize(15, 3).Value
    End With
的值,而他只想把RNG(2 TO 16,3 TO 5)範圍的值取出
作者: GBKEE    時間: 2015-6-21 16:50

回復 5# lpk187
樓主不是說,可有辦法不用for...next
作者: PKKO    時間: 2015-6-21 22:24

回復 2# GBKEE


    抱歉,是我沒說清楚,舉例的不太洽當

超版大大您的方式也很好
但假設我的陣列並不是由excel所產生的
而是我自己給他的
DIM AA(1 TO 10,1 TO 5)
然後將運算過的值都輸入到陣列內之後

有沒有甚麼方式可以不透過迴圈
直接將陣列中某一段的資料放置到excel內
平常都是直接使用[A1].RESIZE(1 TO 10,1 TO 5).VALUE=AA
可是如果我要的只是AA裡面的(3 TO 10, 3 TO 5)
這樣要如何一次放到excel內?
有辦法類似[A1].RESIZE(1 TO 10,1 TO 5).VALUE=AA這種的方式嗎?
作者: mpegwmvavi    時間: 2015-6-21 23:43

本帖最後由 mpegwmvavi 於 2015-6-21 23:44 編輯

回復 7# PKKO


我想不到一次性置入的方法,
不過一條一條(直或橫)放進去是做得到的
方法是用Index這個工作表函數
不過還是要迴圈三次,儘管如此,比迴圈m*n次要快得多了

For j=3 to 5
    Cells(1,j-2).Resize(10-3,1)=Application.Index(AA,0,j)
Next

參考網站:
https://usefulgyaan.wordpress.com/2013/06/12/vba-trick-of-the-week-slicing-an-array-without-loop-application-index/
作者: c_c_lai    時間: 2015-6-22 05:03

回復 8# mpegwmvavi
一篇不錯的論述,謝謝你的堤供!
作者: PKKO    時間: 2015-6-22 13:48

回復 8# mpegwmvavi


    沒想到還有這種方法,真是太感謝了!
作者: c_c_lai    時間: 2015-6-22 16:55

回復 1# PKKO
這是我個人的直覺處理方式,僅供你做參考用!
  1. Sub Ex2()
  2.     ' rng = [A5].CurrentRegion '假設UBOUND(RNG)=20 ,UBOUND(RNG,2)=10
  3.     ' Q1:  [A1].Resize(20, 10).Value = rng '我覺得這是將陣列資料放在excel非常快的方式,不曉得還有更快的嬤?
  4.     ' Q2 : 如果RNG這個陣列,我希望它由RNG(2 TO 16,3 TO 5) 放到 [A1].Resize(15, 3).Value這裡面該如何做?因為目前Q1程式碼無法達成這種放置方式
  5.     ' PS:有沒有答案不是迴圈的.CELLS(x,x)=RNG(X,X)的方式

  6.     Dim rng As Variant, MyArr As Variant, chars As String
  7.    
  8.     ' rng = [A30].CurrentRegion '假設UBOUND(RNG)=20 ,UBOUND(RNG,2)=10
  9.     rng = [A30].CurrentRegion
  10.    
  11.     [AA1].Resize(UBound(rng), UBound(rng, 2)) = rng
  12.     '  Q2 : 如果RNG這個陣列,我希望它由RNG(2 TO 16,3 TO 5)
  13.     chars = "A" & Chr(64 + 3 + 1) & (2 + 1) & ":" & "A" & Chr(64 + 3 + (5 - 3 + 1)) & (2 + (16 - 2 + 1))
  14.     MyArr = ThisWorkbook.Worksheets("工作表1").Range(chars).Value
  15.     [AA1:AJ20].Clear
  16.    
  17.     [A1:J20].Clear
  18.     [A1].Resize(15, 3) = MyArr
  19. End Sub
複製代碼

作者: c_c_lai    時間: 2015-6-22 17:47

本帖最後由 c_c_lai 於 2015-6-22 17:50 編輯

回復 1# PKKO
回復 2# GBKEE
其實 GBKEE 先前的回覆 ( #2 ) 也是一個很切實際的範例,茲將它略略修改成 PKKO 的需求:
  1. Sub EX()
  2.     Dim Rng()
  3.         
  4.     ' rng = [A5].CurrentRegion '假設UBOUND(RNG)=20 ,UBOUND(RNG,2)=10
  5.     ' 假設 [A30] 區域為本案例陣列之暫存處裡區塊
  6.     ' [A30].Resize(UBound(Rng), UBound(Rng, 2)) = Rng
  7.    
  8.     chars = Chr(64 + 3 + 1) & (30 + 2) & ":" & Chr(64 + 3 + (5 - 3 + 1)) & (30 + 2 + (16 - 2))
  9.     With Range("A30").CurrentRegion
  10.         Rng = Range(chars).Value
  11.     End With
  12.     [A1].Resize(15, 3) = Rng
  13. End Sub
複製代碼

作者: PKKO    時間: 2015-6-22 18:36

回復 12# c_c_lai


    C大您好:

不曉得下列方法,在實際運算中
那一種速度最快呢?

1: .CELLS(X,X)=RNG(X,X)   =>迴圈法
2: 8 樓提供的INDEX法
3: 您提供的方式,先將完整陣列放置到excel,再取出我要的值,再一次性的放置到原本位置

因為我實驗過一次性放置比迴圈法放置還要快許多
但不曉得1、2、3 哪一種方法會比較快呢?
作者: c_c_lai    時間: 2015-6-23 08:03

回復 13# PKKO
rng 本身存取之內容並非是目前指定的 {A30},那只是個舉例讓你易於理解,
就如你自訂的 RNG=[A5].CURRENTREGION 的位置一樣。此處,重點是在假設
rng 是個已存在值的 Variant 變數值。你希望它從 RNG(2 TO 16,3 TO 5)
"抽取出來" 然後能夠將其內容放置到 [A1].Resize(15, 3) 的位置上,而且
"PS:有沒有答案不是迴圈的.CELLS(x,x)=RNG(X,X)的方式"。這兒並無所謂的
"再一次性的放置到原本位置" 之處理。就如你自己先前舉例欲指定的 [A1]。

前提是要如何達成此構思:
1) 應用 "迴圈" 完成? (#13 - 1 迴圈法、2 INDEX法)。 抑或是
2) 先將 rng 內容至於某區塊,然後再將它依你的需求 (2 TO 16,3 TO 5)
   "抽取出來",置放入你指定的 [A1].Resize(15, 3) 的位置上。
   完成後再將暫存區清除。

至於快慢的問題,礙於個人設備之不同,需要你自行測試其差異性,
11#、12# (GBKEE) 的回覆已經給了你答案了。
作者: PKKO    時間: 2015-6-23 10:15

回復 14# c_c_lai


    感謝C大,已受益良多!
作者: bobomi    時間: 2015-6-23 10:35

本帖最後由 bobomi 於 2015-6-23 10:44 編輯

回復 15# PKKO

想要速度快  用 For.... Next 擷取片段  就是你的最佳選擇
當然還有1個比 For.... Next 快 10倍到萬倍 的方法
但是速度是相對
真正耗時的是    CELLS(X,X)=RNG(X,X)  這個動作

你擷取1次就一定會進行1次 CELLS(X,X)=RNG(X,X)  
假設
For .... Next 片段擷取執行次數   1萬次 -> 耗時 0.15 秒
CELLS(X,X)=RNG(X,X)   執行次數   1萬次  ->  耗時 32 秒
總耗時 = 32 秒 + 0.15 秒 = 32.15 秒

今天你捨棄For .... Next 片段擷取  改用  第1快的擷取法
總耗時會變成 = 32 秒 + 0.01 秒 = 32.01 秒
上面已經提到速度是相對

32.15 秒 和  32.01 秒  你會感受到影響嗎? 完全無感對吧
所以想要快 用 For.... Next 擷取片段  就是你的最佳選擇, 它起碼會是第2快

不要看到有回圈動作就認為它一定慢  
其實看不到回圈動作的, 還是要進行回圈動作的, 只不過這個回圈動作被它吃進去在內部執行罷了 (優勢只在於方便, 換來的常是低速)




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)