Excel memory overflow?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Bassiehetkoekje
Posts: 4
Joined: 20 Feb 2022, 07:28

Excel memory overflow?

05 Apr 2022, 05:08

I made an AHK script that does the following:
  • Open an empty Excel sheet
  • One by one, read a bunch of excel files from a chosen folder and copy the contents of Cell A1
  • Write copied content in the original sheet
I use

Code: Select all

Loop, Files, % Path "\Invoice*.xlsx"
{
	WB := ComObjGet(A_LoopFileFullPath)
	; do stuff
}
to get values from the excel files to read.

The script works as expected, but after about 300 files Excel stops reacting and complains about insufficient memory. The actual message is this:
There isn't enough memory to complete this action.
Try using less data or closing other applications.
To increase memory availability, consider:
- Using a 64-bit version of Microsoft Excel.
- Adding memory to your device
User avatar
boiler
Posts: 17222
Joined: 21 Dec 2014, 02:44

Re: Excel memory overflow?

05 Apr 2022, 05:33

Try this:

Code: Select all

Loop, Files, % Path "\Invoice*.xlsx"
{
	WB := ComObjGet(A_LoopFileFullPath)
	; do stuff
	WB.Close()
}
User avatar
flyingDman
Posts: 2833
Joined: 29 Sep 2013, 19:01

Re: Excel memory overflow?

05 Apr 2022, 12:13

To read data from a large number of excel files, ADODB is significantly faster than ComObjGet. In test ADODB was ~ 16.5 times faster than ComObjGet (6.3 sec vs 103.5 sec).
I created a function - getXcells() - to extract data from Excel sheets using ADODB. You will need to install the Microsoft Database Engine, a free utility which can be found here: https://www.microsoft.com/en-us/download/details.aspx?id=54920 if not already installed on your PC.
The function:

Code: Select all

getXcells(datasource, sheet := "sheet1") 
	{
	global colcnt, rowcnt
	arr := [], rowcnt := 0
	objConnection := ComObjCreate("ADODB.Connection"), 	objRecordSet := ComObjCreate("ADODB.Recordset")
	try objConnection.Open("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" . dataSource . "; Extended Properties='Excel 12.0 xml;HDR=no;IMEX=1';")
	catch
		{
		msgbox,48,, Error! Data could not be retrieved, 2
		return
		}
	try objRecordset.Open("Select * FROM [" Sheet "$]", objConnection, 3, 3, 1)   ; adOpenStatic = 3 , adLockOptimistic = 3 , adCmdText = 1
	catch
		{
		msgbox,48,, Error! %Sheet% does not exist, 2
		return
		}
	pFields := objRecordset.Fields
	while !objRecordset.EOF
		{
		row := [], ++rowcnt
		Loop, % colcnt := pFields.Count
			row[A_Index] := pFields.Item(A_Index-1).value
		arr.push(row)
		objRecordset.MoveNext
		}
	objRecordSet.Close()
	objConnection.Close()
	objRecordSet := ""
	objConnection := ""	
	return arr
	}
To get the content of cell A1 out of each of the files in the loop, you can use this:

Code: Select all

Loop, Files, % Path "\Invoice*.xlsx"
	lst .= getXcells(A_LoopFileFullPath, "sheet1").1.1 "`n"
msgbox % lst
14.3 & 1.3.7
Bassiehetkoekje
Posts: 4
Joined: 20 Feb 2022, 07:28

Re: Excel memory overflow?

16 Apr 2022, 12:36

Thanks so much for your replies @boiler and @flyingDman . I actually pressed 'post' accidentally, but it seems like that was enough info to answer my unasked question ;)

WB.Close() worked! Now I feel silly... I was assuming that there would be garbage collection every time I re-initialized the WB variable. But Excel itself kept everything in memory it seems.

I didn't implement @flyingDman's solution yet, because I just wanted to get it working without too much hassle and it's fast enough for my purposes (1 min). However, I'm intrigued by the suggested speed difference so I'll try it out later :)

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Spawnova, tabr3 and 221 guests