返回列表 上一主題 發帖

用迴圈抓資料越跑越慢,該如何釋放記憶體?

回復 10# GBKEE


感謝G大的分享

不過小弟我還是不太了解,為什麼在EXCEL中用迴圈匯入資料會越匯越慢....
我使用的是win 7、64位元、6G記憶體
平常有清除系統垃圾的習慣,且在執行程式時,不論CPU或是記憶體都顯示尚有多餘的資源(從工作管理員觀察)
況且,如果是因為系統資源不足所導致的問題,應該不會出現執行程式初期速度較快,而執行到後面速度就整個拖下來的情況才是
應該是從頭到尾都很慢才是
不曉得我這樣推論是否正確呢?

TOP

回復 11# sasho
你使用的是EXCEL 2010 ,可否上傳你的檔案.
我來試試  XP、32位元、1G記憶體 ,2003版本的速度
感恩的心......(在麻辣家族討論區.用心學習會有進步的)
但資源無限,後援有限,  一天1元的贊助,人人有能力.

TOP

回復 12# GBKEE


感謝G版大的幫忙,因為我無法上傳檔案,所以把檔案放在如下的dropbox的網址
另外,最近幾天測試的結果,發現問題是出在兩個部分
一個是匯入網頁資料,另一個是將匯入資料另存成csv檔
根據記錄的資料,這兩個動作都會隨著迴圈越跑越多而越來越慢
還請G版大指點一下,謝謝

https://www.dropbox.com/s/n0ycnc7q4gqtbrb/%E6%8A%93%E5%8F%96%E4%B8%8A%E5%B8%82%E8%B3%87%E6%96%99.xls

TOP

本帖最後由 GBKEE 於 2014-6-25 13:39 編輯

回復 13# sasho
你原本的 Sub 執行(),在我的PC沒有你所說的越來越慢的情形.速度與Main() 的記錄檔差不多.

整理一下,附上 Sub Main() 的記錄檔

Ex.rar (10.87 KB)
  1. Option Explicit
  2. Dim IE As Object, Query_Sh As Worksheet, CsvPath As String, SaveDate As String
  3. Dim t As Date, StartTime As Date, 記錄檔 As String, stockid As Range, spListCount As Integer
  4. Sub Main()
  5.     Dim i As Integer
  6.     t = Time
  7.     StartTime = Time
  8.     CsvPath = "D:\TSE\"
  9.     目錄 CsvPath
  10.     記錄檔 = CsvPath & "Main_Record.TXT"
  11.     If Dir(記錄檔) <> "" Then Kill 記錄檔
  12.     暫存頁 "temp"
  13.     xRecond 0, "程式開始執行" & vbCrLf
  14.     Set stockid = Sheets("工作表1").Range("A2")
  15.     stockid.Parent.Activate
  16.     Do While stockid <> ""
  17.         Application.ScreenUpdating = True
  18.         stockid.Select
  19.         Application.ScreenUpdating = False
  20.         StartTime = Time
  21.         spListCount = 資料頁數
  22.         If spListCount > 0 Then
  23.             i = i + 1
  24.             xRecond i, stockid & vbTab & "資料匯入"
  25.             資料匯入
  26.             整理
  27.             存檔
  28.             xRecond i, stockid.Value & vbTab & "存檔完畢 " & Format(Time - StartTime, "共SS秒") & vbCrLf
  29.         End If
  30.         Set stockid = stockid.Offset(1)
  31.     Loop
  32.     IE.Quit
  33.     Application.DisplayAlerts = False
  34.     Query_Sh.Delete
  35.     Application.DisplayAlerts = True
  36.     Workbooks.Open 記錄檔
  37.     MsgBox "共存 ""(" & i & ") csv檔完畢" & vbTab & "費時 " & Format(Time - t, "nn分ss秒")
  38. End Sub
  39. Private Sub 暫存頁(temp As String)
  40.     On Error Resume Next
  41.     Set Query_Sh = Sheets(temp)
  42.     If Err.Number = 9 Then
  43.         Sheets.Add(, Sheets(1)).Name = temp
  44.         Set Query_Sh = Sheets(temp)
  45.     End If
  46. End Sub
  47. Private Sub 資料匯入()
  48.     Dim strURL As String
  49.     strURL = "URL;" & "http://bsr.twse.com.tw/bshtm/bsContent.aspx?StartNumber=" & stockid & "&FocusIndex=All_" & spListCount
  50.     With Query_Sh
  51.         .UsedRange.Clear
  52.         With .QueryTables.Add(strURL, Query_Sh.[a1])
  53.             .WebFormatting = xlWebFormattingNone
  54.             .WebSelectionType = xlSpecifiedTables
  55.             .WebTables = "5,table2"
  56.             .Refresh 0
  57.             .Delete
  58.         End With
  59.     End With
  60. End Sub
  61. Private Sub 整理()
  62.     Dim i As Integer
  63.     With Sheets("temp")
  64.         SaveDate = Format(.Range("B1"), "YYYYMMDD")
  65.         With .UsedRange.Range("A:A")
  66.             .SpecialCells(xlCellTypeConstants, xlTextValues).EntireRow.Delete
  67.             .SpecialCells(xlCellTypeBlanks).EntireRow.Delete
  68.         End With
  69.         .UsedRange.Columns("F:J").Cut
  70.         .Range("A" & .Rows.Count).End(xlUp).Offset(1).Insert Shift:=xlDown
  71.         .UsedRange.Sort Key1:=.Range("A1"), Order1:=xlAscending, Header:=xlNo
  72.         .UsedRange.Columns("B:B").Insert Shift:=xlToRight
  73.         .UsedRange.Columns(1) = SaveDate
  74.         .UsedRange.Columns(2) = stockid
  75.          For i = 1 To .UsedRange.Rows.Count
  76.             .Cells(i, 3) = Left(.Cells(i, 3), 4)
  77.             .Cells(i, 5) = .Cells(i, 5).Value / 1000
  78.             .Cells(i, 6) = .Cells(i, 6).Value / 1000
  79.         Next
  80.     End With
  81. End Sub
  82. Private Sub 目錄(xPath As String)
  83.     Dim SP As Variant, P As String, i As Integer
  84.     SP = Split(xPath, "\")
  85.     P = SP(0)
  86.     With CreateObject("Scripting.FileSystemObject")
  87.         For i = 1 To UBound(SP)
  88.             P = P & "\" & SP(i)
  89.             If .FolderExists(P) = False Then .CreateFolder (P)
  90.         Next
  91.     End With
  92. End Sub
  93. Private Sub 存檔()
  94.     Dim CSVfolder As String, CSVfile As String
  95.     CSVfolder = CsvPath & SaveDate & "\"
  96.     目錄 CSVfolder
  97.     CSVfile = CSVfolder & stockid & "_" & SaveDate & ".csv"
  98.     If Dir(CSVfile) <> "" Then Kill CSVfile
  99.     Query_Sh.Copy
  100.     With ActiveWorkbook
  101.         .SaveAs Filename:=CSVfile, FileFormat:=xlCSV
  102.         .Close 0
  103.     End With
  104. End Sub
  105. Private Sub xRecond(i As Integer, xSub As String)
  106.     Dim S As String
  107.     S = Time & vbTab & Format(Time - t, " 第nn分ss秒") & vbTab & " 第 " & i & " 個Csv檔 " & xSub
  108.     Close #1
  109.     Open 記錄檔 For Append As #1
  110.     Print #1, S
  111.     Close #1
  112.     Application.StatusBar = S
  113. End Sub
  114. Private Function 資料頁數() As Integer   '取得頁數
  115.     If IE Is Nothing Then
  116.         Set IE = CreateObject("InternetExplorer.Application")
  117.         IE.Navigate "http://bsr.twse.com.tw/bshtm/bsMenu.aspx"
  118.         IE.Visible = True  '可不顯示
  119.     End If
  120.     With IE
  121.         Do:  Loop While .Busy Or IE.ReadyState <> 4
  122.         With .document
  123.             .getElementByID("txtTASKNO").Value = stockid
  124.             .getElementByID("btnOK").Click
  125.             Do: Loop While IE.Busy Or IE.ReadyState <> 4 Or .getElementByID("sp_ListCount") Is Nothing
  126.             資料頁數 = Val(.getElementByID("sp_ListCount").innertext)
  127.         End With
  128.     End With
  129. End Function
複製代碼
感恩的心......(在麻辣家族討論區.用心學習會有進步的)
但資源無限,後援有限,  一天1元的贊助,人人有能力.

TOP

回復 14# GBKEE

實際測試G大所提供的程式,確實比之前的那個還要快很多
仔細比對後,我發現主要的問題是在於調整格式這部分

因為這些資料我會再匯入到mysql當中,所以資料格式不能出錯
所以在最一開始我所提供的程式中,在sub 調整格式()的最後,我有再加上一段指令
cells.NumberFormatLocal = "G/通用格式"
而這段指令是G大所提供的程式碼中所沒有的
目前推測就是因為這段敘述,導致整個程式速度降了下來
以及程式執行過程,EXCEL所占用的記憶體不斷攀高

感謝G大的指點,受教了!

TOP

回復 15# sasho
  1. Cells.NumberFormatLocal = "G/通用格式"
  2. 可改成(縮小範圍)
  3. UsedRange.NumberFormatLocal = "G/通用格式"
複製代碼
感恩的心......(在麻辣家族討論區.用心學習會有進步的)
但資源無限,後援有限,  一天1元的贊助,人人有能力.

TOP

        靜思自在 : 人要自愛,才能愛普天下的人。
返回列表 上一主題