Pasting Excel data to webform

I’ve got a large amount of data in Excel that I need to paste into a webform, hit the “send” button, wait for the page to reload, and continue where it left off.

My Excel data is 7 columns, roughly 500 rows.

I tried to follow a similar script by Craig Smith where another user us asking for similar help but I’m getting stuck. Here’s the post: https://macscripter.net/viewtopic.php?id=20318

I used Craigs script to put the data in to an array/list, but I’m not sure how to insert that data into the form.

set {master_data, dummy} to {{}, {}}
tell application "Microsoft Excel"
	repeat with r_row from 2 to 3
		repeat with c_col from 1 to 7
			copy value of cell c_col of row r_row of active sheet to the end of dummy
		end repeat
		set end of master_data to dummy
		set dummy to {}
	end repeat
end tell
master_data

The webform has the following html boxes, if we’re using javascript their ID is the same as the Name
-foodColor
-foodSender
-foodReceiver
-foodValue
-foodAmount
-foodName
-foodShape

The Excel sheet I have contains those 7 items listed as data in the columns, so something like:

[format]
Color Sender Receiver Value Amount Name Shape

Red Bill Jim 100 40 Apples Round

Blue James Mike 400 10 Berries Oval

Green Pat Sam 130 5 Grapes Round
[/format]

I just need to paste each Excel column to its corresponding webform field, hit a “Send” button, and give it a minute to send, then move on to the next row of data.

I don’t know if there is a better way to do it other than an array, any help is much appreciated.

I’m not 100% sure

JavaScript with:
document.getElementById(‘Id’).value=‘new value’;

Have you try that ?

You could do a simple test with this example.
Go here with Safari: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

Now run the script below.

set theScript to "function testFunc() {
//
var v = document.getElementById('main-q').value='searchString';
return v
}
testFunc()
"
tell application "Safari"
	do JavaScript theScript in document 1
end tell

In the search text field you will now have a string: searchString

The post you reffer is related to reading and parsing the webpage content, and not to sending your data to webpage. For you task you should use GUI scripting the dialog of webform.

To find what is text field’s names and how to enter the data, use Automator’s Record button. Fill manually the webform while recording is on. Then see at what wrote the Automator for your actions.

To find how to open new empty webform do the same: use Automator’s Record button. For example, 1) set Automator’s Record on 2) click “Login” link of this MacScripter webpage 3) stop Record of Automator 4) See at what wrote the Automator for your action (click).

See here what wrote the Automator for me, when i clicked the “Login” link of this page:

“click static text 1 of UI Element "Login" of group 7 of group 2 of UI Element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window "MacScripter / Pasting Excel data to webform" of application process "Safari"”

Now, I know: I can do something like this (the username and password are pseudo):


tell application "Safari"
	open location "https://macscripter.net/viewtopic.php?id=48118"
	delay 5 -- wait the loading
	activate
end tell

-- open the webform
tell application "System Events" to tell process "Safari" to tell window 1
	click static text 1 of UI element "Login" of group 7 of group 2 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1
end tell

-- Now, filling the form. The last Return sends the filled webform
tell application "System Events" to keystroke "theUserName" & return & "thePassword" & return & return

NOTE: for each row, whole the code above should be putted in the repeat loop (with rows)

Thanks for the help! I figured out how to enter the data but I’m not sure how to loop it. Any ideas?

set {foodColor, foodSender, foodReceiver, foodValue, foodAmount, foodName, foodShape} to getData()

repeat with i from 1 to count foodColor
	tell application "Safari"
		activate
		do JavaScript "document.getElementById('foodColor').value= '" & foodColor& "';" in document 1
		do JavaScript "document.getElementById('foodSender').value= '" & foodSender& "';" in document 1
		do JavaScript "document.getElementById('foodReceiver').value= '" & foodReceiver& "';" in document 1
		do JavaScript "document.getElementById('AddValue').value='Yes';" in document 1
		do JavaScript "document.getElementById('foodValue').value= '" & foodValue& "';" in document 1
		do JavaScript "document.getElementById('foodAmount').value= '1';" in document 1
		do JavaScript "document.getElementsByName('foodName')[0].value= '" & foodName& "';" in document 1
		do JavaScript "document.getElementsByName('foodShape')[0].value= '" & foodShape& "';" in document 1

As for getting the data from Excel, it looks like I can do either method, not sure which is best.

Method 1

set {master_data, dummy} to {{}, {}}
tell application "Microsoft Excel"
   repeat with r_row from 2 to 3
       repeat with c_col from 1 to 7
           copy value of cell c_col of row r_row of active sheet to the end of dummy
       end repeat
       set end of master_data to dummy
       set dummy to {}
   end repeat
end tell
master_data

Method 2

on getData() -- this part grabs excel data, I could use the 
	set colA to {}
	set colB to {}
	set colC to {}
	set colD to {}
	set colE to {}
	set colF to {}
	set colG to {}
	tell application "Microsoft Excel"
		
		activate
		tell active sheet
			set lastRow to first row index of (get end (last cell of column 1) direction toward the top)
			
			repeat with i from 2 to lastRow
				set end of colA to (value of range ("A" & i))
				set end of colB to (value of range ("B" & i))
				set end of colC to (value of range ("C" & i))
				set end of colD to (value of range ("D" & i))
				set end of colE to (value of range ("E" & i))
				set end of colF to (value of range ("F" & i))
				set end of colG to (value of range ("G" & i))
			end repeat
		end tell
	end tell
	
	return {colA, colB, colC, colD, colE, colF, colG}
end getData

I’m not sure which method would be best and I’m not sure how to loop it.

I would build the text for each row as a whole, to keystroke it then with System Events. Here’s the pseudocode (as I don’t know your webpage):

set formDataList to {}

tell application "Microsoft Excel" to tell active workbook to tell active sheet
	repeat with rowIndex from 2 to 3
		set theText to (value of cell ("A" & i)) & return
		set theText to theText & (value of cell ("A" & i)) & return
		set theText to theText & (value of cell ("B" & i)) & return
		set theText to theText & (value of cell ("C" & i)) & return
		set theText to theText & (value of cell ("D" & i)) & return
		set theText to theText & (value of cell ("E" & i)) & return
		set theText to theText & (value of cell ("F" & i)) & return
		set theText to theText & (value of cell ("G" & i)) & return
		set end of formDataList to theText
	end repeat
end tell -- formDataList is now ready

-- now go to website
repeat with formData in formDataList
	tell application "Safari"
		open location "https://macscripter.net/viewtopic.php?id=48118"
		delay 5 -- wait the loading
		activate
	end tell
	
	-- open the webform
	tell application "System Events" to tell process "Safari" to tell window 1
		click static text 1 of UI element "Login" of group 7 of group 2 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1
	end tell
	
	-- Now, filling the form. The last Return sends the filled webform
	tell application "System Events" to keystroke formData & return
end repeat

Thanks for the Help KniazidisR.

When running the script, it gives me the following error: [format]error “The variable i is not defined.” number -2753 from “i” [/format]

It’s referencing the first “set TheText to” call, specifically (“A” & i) but I assume it will fail with the other columns referenced as well.

Also, for the form fill, I’ve already got it working with the javascript calls:

tell application "Safari"
       activate
       do JavaScript "document.getElementById('foodColor').value= '" & foodColor& "';" in document 1
       do JavaScript "document.getElementById('foodSender').value= '" & foodSender& "';" in document 1
       do JavaScript "document.getElementById('foodReceiver').value= '" & foodReceiver& "';" in document 1
       do JavaScript "document.getElementById('AddValue').value='Yes';" in document 1
       do JavaScript "document.getElementById('foodValue').value= '" & foodValue& "';" in document 1
       do JavaScript "document.getElementById('foodAmount').value= '1';" in document 1
       do JavaScript "document.getElementsByName('foodName')[0].value= '" & foodName& "';" in document 1
       do JavaScript "document.getElementsByName('foodShape')[0].value= '" & foodShape& "';" in document 1

so I’m not sure if the UI scripting is necessary for putting the data in, but if it is I can definitely mess around with it to fit it in.

Maybe you could try this…

-- GET THE DATA FROM EXCEL

-- log the values from excel to check its correct.
log {foodColor, foodSender, foodReceiver, foodValue, foodAmount, foodName, foodShape}

set theData to {foodColor, foodSender, foodReceiver, foodValue, foodAmount, foodName, foodShape}

-- Repeat loop
repeat with i from 1 to (count theData)
	set {theName, theValue} to {name of item i of theData, item i of theData}
	setElementById(theName, theValue)
end repeat

on setElementById(_theID,_theValue)
	tell application "Safari"
		do JavaScript "document.getElementById('" & _theID & "').value='" & _theValue & "';" in document 1
	end tell
end setElementById

I’m definitely dense, I can’t seem to figure out why it isn’t working. I think I’m combining too many parts of different scripts. Here’s what I have so far:

---GET EXCEL DATA--
on getData()
	set colA to {}
	set colB to {}
	set colC to {}
	set colD to {}
	set colE to {}
	set colF to {}
	set colG to {}
	tell application "Microsoft Excel"
		
		activate
		tell active sheet
			set lastRow to first row index of (get end (last cell of column 1) direction toward the top)
			
			repeat with i from 2 to lastRow
				set end of colA to (value of range ("A" & i))
				set end of colB to (value of range ("B" & i))
				set end of colC to (value of range ("C" & i))
				set end of colD to (value of range ("D" & i))
				set end of colE to (value of range ("E" & i))
				set end of colF to (value of range ("F" & i))
				set end of colG to (value of range ("G" & i))
			end repeat
		end tell
	end tell
	
	return {colA, colB, colC, colD, colE, colF, colG}
end getData

--SET VARIABLE--

set theData to {foodColor, foodSender, foodReceiver, foodValue, foodAmount, foodName, foodShape}

---PASTES DATA TO THE WEBFORM---
repeat with i from 1 to count theData
	tell application "Safari"
		activate
		do JavaScript "document.getElementById('foodColor').value= '" & foodColor & "';" in document 1
do JavaScript "document.getElementById('foodSender').value= '" & foodSender & "';" in document 1
do JavaScript "document.getElementById('foodReceiver').value= '" & foodReceiver & "';" in document 1
do JavaScript "document.getElementById('AddValue').value='Yes';" in document 1
do JavaScript "document.getElementById('foodValue').value= '" & foodValue & "';" in document 1
do JavaScript "document.getElementById('foodAmount').value= '1';" in document 1
do JavaScript "document.getElementsByName('foodName')[0].value= '" & foodName & "';" in document 1
do JavaScript "document.getElementsByName('foodShape')[0].value= '" & foodShape & "';" in document 1
	end tell
end repeat

Running this script works, but it only enters the first row of data, I can’t seem to make it loop to the next set of data after waiting ~5 seconds for the page to reload.

I think you should read the AppleScript Reference Guide how to make repeat loop…
Becouse I think you didn’t understand my code.

set {foodColor, foodSender, foodReceiver, foodValue, foodAmount, foodName, foodShape} to {"chocolatebrown", "iceScreamTruck", "children", "dessert", "everything", "gelato", "cold"}

set theData to {foodColor, foodSender, foodReceiver, foodValue, foodAmount, foodName, foodShape}

return theData
-- Repeat loop
repeat with i from 1 to (count theData)
	set theValue to item i of theData
	log theValue
end repeat

so

– item 1 (or first item in the repeat loop) is foodColor, its value are chocolateBrown

return item 1 of theData

and if we call directly…

return foodColor

It is very difficult to help without knowing about a specific site. Your last script clarifies something. Now I understand that your site allows you to fill a form using Javascript.

It is not yet clear whether the empty form appears on its own after sending the next data set, or if you have to open the empty webform yourself every time.

Let’s say that the empty form appears on its own. Then, I could make some necessary changes to your last script:


---GET EXCEL DATA--
on getData()
	set colA to {}
	set colB to {}
	set colC to {}
	set colD to {}
	set colE to {}
	set colF to {}
	set colG to {}
	tell application "Microsoft Excel"
		
		activate
		tell active sheet
			set lastRow to first row index of (get end (last cell of column 1) direction toward the top)
			
			repeat with i from 2 to lastRow
				set end of colA to (value of range ("A" & i))
				set end of colB to (value of range ("B" & i))
				set end of colC to (value of range ("C" & i))
				set end of colD to (value of range ("D" & i))
				set end of colE to (value of range ("E" & i))
				set end of colF to (value of range ("F" & i))
				set end of colG to (value of range ("G" & i))
			end repeat
		end tell
	end tell
	
	return {colA, colB, colC, colD, colE, colF, colG}
end getData

--SET VARIABLE--

set {foodColor, foodSender, foodReceiver, foodValue, foodAmount, foodName, foodShape} to getData() -- EDITED

---PASTES DATA TO THE WEBFORM---
repeat with i from 1 to lastRow - 1 -- EDITED
	tell application "Safari"
		activate
		do JavaScript "document.getElementById('foodColor').value= '" & (item i of foodColor) & "';" in document 1 -- EDITED
		do JavaScript "document.getElementById('foodSender').value= '" & (item i of foodSender) & "';" in document 1 -- EDITED
		do JavaScript "document.getElementById('foodReceiver').value= '" & (item i of foodReceiver) & "';" in document 1 -- EDITED
		do JavaScript "document.getElementById('AddValue').value='Yes';" in document 1
		do JavaScript "document.getElementById('foodValue').value= '" & (item i of foodValue) & "';" in document 1 -- EDITED
		do JavaScript "document.getElementById('foodAmount').value= '1';" in document 1
		do JavaScript "document.getElementsByName('foodName')[0].value= '" & (item i of foodName) & "';" in document 1 -- EDITED
		do JavaScript "document.getElementsByName('foodShape')[0].value= '" & (item i of foodShape) & "';" in document 1 -- EDITED
	end tell
end repeat

NOTE: how you send the filled form is unclear too. You click some “Send” button using JavaScript?

Thanks KniazidisR, that was the correct guess and it appears to be working as needed! I really appreciate the help, it cleared a lot up and I learned quite a bit.