Speed of AppleScript vs. VBA in Excel

Hi,

I recently had to process a few large (>30,000 rows) Excel files, parsing through them using the Find command, extracting selected pieces of data, and constructing a new worksheet with the extracted data. I first attempted this in AppleScript, but it took a very long time to run for each file, maybe 3-5 hours. I then wrote essentially the same code in VBA using Excel on a Windows machine, and this code ran in about 1 hour. The Mac that I ran the AppleScript on is a 867 Mhz PowerBook with 1.125 Gb of RAM running Excel 2008 under OS X 10.5.6, and the Windows machine I used is a 350 Mhz machine with 384 Mb of RAM running Excel 2002. I don't want to start any "religious" wars, but I'm curious as to whether AppleScript code is really that much slower than VBA code. I tried running the AppleScript with the Excel file "hidden" (I clicked the yellow button on the window), and I also tried saving the script as an "Application", which I thought would speed things up, but didn't. At this point, I don't want to get into any particulars of what methods I called in the script, but I'm looking for general feedback regarding the relative speeds of each technology, and what I might be able to do to speed up the AppleScripts.

Thanks,

Ken

12 G4 PowerBook, Mac OS X (10.5.3), 1.125 Gb RAM

Posted on May 11, 2009 5:01 PM

Reply
4 replies

May 11, 2009 6:35 PM in response to Kenneth Hjulstrom

The various scripting languages have different design goals, so there are different optimizations - AppleScript is set up to be more of a general purpose application scripting tool.

AppleScript isn't known for being particularly speedy, but there are a variety of things that can hurt performance, such as improperly used or placed tell statements (there is some overhead in sending messages to applications). There are also a variety of things that can be used to improve performance, such as script objects or using a more appropriate tool such as a shell script. Without seeing some specific code examples, it is hard to say.

May 12, 2009 5:39 AM in response to red_menace

Hi,

Thanks for the info. FYI, here's the script. It's designed to parse a file of invoice data, skipping the line item rows and constructing a new sheet containing just the pertinent invoice data and total for each invoice. It provides the correct output, but it's just slow. Any suggestions on improving the code would be much appreciated:

+++++++++++++++++++++++++++++++++++++++
-- Start the timer to time the execution of this script
set start_timer to current date

tell application "Microsoft Excel"

-- Initialize current invoice values
set currentCustNum to ""
set currentCustName to ""
set currentInvoiceNum to ""
set currentInvoiceDate to ""
set currentInvoiceTotal to ""

-- No invoice has been found yet
set firstFoundInvoiceDate to ""
set Done to false

-- Keep track of how many invoices have been processed
set numInvoicesProcessed to 0

-- Find the first occurrence of the row containing the invoice number, date, customer number and customer name
set foundInvoiceDate to (find (range "G:G" of worksheet "Sheet1") what "Date:")

-- Find the first occurrence of the row containing the invoice total
set foundInvoiceTotal to (find (range "B:B" of worksheet "Sheet1") what "INVOICE TOTALS:")

-- Process each invoice
repeat while not Done

set currentRowNum to first row index of foundInvoiceDate

-- Remember the location of the date of the first invoice processed
if numInvoicesProcessed = 0 then

-- Remember the location of the first invoice date found
set firstFoundInvoiceDate to foundInvoiceDate

end if

-- Count the invoice being processed now
set numInvoicesProcessed to numInvoicesProcessed + 1

-- Get the current invoice date
set currentInvoiceDate to value of foundInvoiceDate
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to " "
set currentInvoiceDate to (text item 2 of currentInvoiceDate) as text
set AppleScript's text item delimiters to tid
-- display dialog currentInvoiceDate

-- Get the current invoice number
set currentInvoiceNum to value of cell 2 of row currentRowNum
-- display dialog currentInvoiceNum

-- Get the current customer number
set currentCustNum to value of cell 12 of row currentRowNum
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to " - "
set currentCustNum to (text item 1 of currentCustNum) as text
set AppleScript's text item delimiters to tid
-- display dialog currentCustNum

-- Get the current customer name
set currentCustName to value of cell 12 of row currentRowNum
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to " - "
set currentCustName to (text item 2 of currentCustName) as text
set AppleScript's text item delimiters to tid
-- display dialog currentCustName

-- Look for this invoice's "INVOICE TOTALS:" line
set currentTotalRowNum to first row index of foundInvoiceTotal

set currentInvoiceTotal to string value of cell 20 of row currentTotalRowNum
-- display dialog currentInvoiceTotal

-- Save the current invoice's data fields in the "InvoiceSummaries" sheet
-- activate object worksheet "InvoiceSummaries"
set the value of cell 1 of row numInvoicesProcessed of worksheet 2 to currentInvoiceNum
set the value of cell 2 of row numInvoicesProcessed of worksheet 2 to currentInvoiceDate
set the value of cell 3 of row numInvoicesProcessed of worksheet 2 to currentInvoiceTotal
set the value of cell 4 of row numInvoicesProcessed of worksheet 2 to currentCustNum
set the value of cell 5 of row numInvoicesProcessed of worksheet 2 to currentCustName
-- activate object worksheet "Sheet1"

-- Look for the next invoice to process
set foundInvoiceDate to (find (range "G:G" of worksheet "Sheet1") what "Date:" after foundInvoiceDate)
if foundInvoiceDate = firstFoundInvoiceDate then
set Done to true
else
set foundInvoiceTotal to (find (range "B:B" of worksheet "Sheet1") what "INVOICE TOTALS:" after foundInvoiceTotal)
end if

end repeat

set run_time to (current date) - start_timer

set the value of cell 1 of row (numInvoicesProcessed + 4) of worksheet 2 to (" " & numInvoicesProcessed & " invoices were processed. The elapsed time was " & run_time & " seconds.")
-- display dialog "Processing completed! " & numInvoicesProcessed & " invoices were processed. The elapsed time was " & run_time & " seconds."

end tell
+++++++++++++++++++++++++++++++++++++++

May 12, 2009 6:47 AM in response to Kenneth Hjulstrom

I'm using Numbers ’09 as a spreadsheet, not Excel, but maybe my suggestion can help anyway.
With Numbers, I get the fastest execution times by first saving the whole initial sheet into a variable, for example:
*set my_sheet to value of cells of rows of table 1 of sheet "Pierre"*
I then manipulate these data as lists (see my preceding message about large lists) or strings in AppleScript, and finally copy the modified data into a new sheet.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Speed of AppleScript vs. VBA in Excel

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.