i have a certain problem with A VBScript when i try to automate a procedure with VBA/VBS macro.
It enters a contract number in VBS and does some standardized changes in VA03, but for some there are some incoplete information, then this pop-up window appears:
I only want my script to click Save and continue in case this happens for a certain contract number.
It did not work with Applications.DisplayAlerts = False, and also i guess it will not work with Error Handler as practically this is not an Error.
It should be with a simple IF statement, but i do not know how i should put the wording.
Can anyone please help, my research in the net got me nowhere :(
Code (Although it is working, i only need a piece which will handle the above stopper):
today = Format(Date, "dd.mm.yyyy")
Application.DisplayAlerts = False
'We declared the variables for the while function in excel
Dim cont As String
Dim row As Integer
Dim rep As String
Dim j As Integer
j = 2
'Those are the commands with which we make SAP available for the VBA code
Set SapGuiAuto = GetObject("SAPGUI")
Set SAPApp = SapGuiAuto.GetScriptingEngine
Set SAPCon = SAPApp.Children(0)
Set Session = SAPCon.Children(0)
If IsObject(WScript) Then
WScript.ConnectObject Session, "on"
WScript.ConnectObject Application, "on"
End If
Session.findById("wnd[0]").maximize
Session.findById("wnd[0]/tbar[0]/btn[3]").press
Session.findById("wnd[0]/tbar[0]/btn[3]").press
Session.findById("wnd[0]/tbar[0]/okcd").Text = "va42"
Session.findById("wnd[0]").sendVKey 0
'We start the loop inside the macro book and give values to our variables
With ThisWorkbook
While Cells(j, 1) <> ""
cont = Cells(j, 1).Value
row = Cells(j, 3).Value
rep = Cells(j, 4).Value
' enter VBS code
'In this part we change the inst to REMV
Session.findById("wnd[0]").maximize
Session.findById("wnd[0]/usr/ctxtVBAK-VBELN").Text = cont
Session.findById("wnd[0]/usr/ctxtVBAK-VBELN").caretPosition = 8
Session.findById("wnd[0]").sendVKey 0
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/ssubSUBSCREEN_BODY:SAPMV45A:4426/subSUBSCREEN_TC:SAPMV45A:4908/tblSAPMV45ATCTRL_U_ERF_KONTRAKT/ctxtVBAP-KDMAT[5," & CStr(row) & "]").SetFocus
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/ssubSUBSCREEN_BODY:SAPMV45A:4426/subSUBSCREEN_TC:SAPMV45A:4908/tblSAPMV45ATCTRL_U_ERF_KONTRAKT/ctxtVBAP-KDMAT[5," & CStr(row) & "]").caretPosition = 6
Session.findById("wnd[0]").sendVKey 2
'change date
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_ITEM/tabpT\03").Select
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP/tabpT\03/ssubSUBSCREEN_BODY:SAPLV45W:4201/ctxtVEDA-VDEMDAT").Text = today
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP/tabpT\03/ssubSUBSCREEN_BODY:SAPLV45W:4201/ctxtVEDA-VDEMDAT").SetFocus
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP/tabpT\03/ssubSUBSCREEN_BODY:SAPLV45W:4201/ctxtVEDA-VDEMDAT").caretPosition = 10
'change INST to REMV
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP/tabpT\10").Select
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_ITEM/tabpT\10/ssubSUBSCREEN_BODY:SAPMV45A:4454/ctxtVBAP-KDMAT").Text = rep
'Deletes the first line in Technical Objects and saves the changes
Session.findById("wnd[0]/mbar/menu[3]/menu[9]").Select
Session.findById("wnd[0]/usr/tblSAPLIWOLOBJK_220").getAbsoluteRow(0).Selected = True
Session.findById("wnd[0]/tbar[1]/btn[19]").press
Session.findById("wnd[1]/usr/btnSPOP-OPTION1").press
Session.findById("wnd[0]/tbar[0]/btn[3]").press
Session.findById("wnd[0]/tbar[0]/btn[11]").press
'we make sure the loop goes through every row and then end it
j = j + 1
Wend
End With
End Sub
Best regards,
Mihail
First, I would record the missing piece of vbs program. Then you have to recognize where in the main program this piece must be installed. But I suspect it will happen after saving. The rough structure might look like this:
. . .
Session.findById("wnd[0]/tbar[0]/btn[11]").press
'------------------------------ new ---------------------------
on error resume next
'Suppose that's the missing piece of program
session.findById("wnd[1]/usr/btnSPOP-OPTION1").press
on error goto 0
'------------------------------ new ---------------------------
'we make sure the loop goes through every row and then end it
j = j + 1
Wend
. . .
Regards,
ScriptMan
I added the solution proposed by Script man above!
It worked perfectly!
Related
I've created a macro that uses 5 columns to paste data into SAP GUI using a loop. However, once it gets to row 30 or 40, it stops pasting the data correctly where it pastes the same number. Not sure if I should add something to enhance the code? All responses will be greatly appreciated, thank you!
On Error Resume Next
Dim Application
If Not IsObject(Application) Then
Set SapGuiAuto = GetObject("SAPGUI")
Set Application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(Connection) Then
Set Connection = Application.Children(0)
End If
If Not IsObject(session) Then
Set session = Connection.Children(0)
End If
If IsObject(WScript) Then
WScript.ConnectObject session, "on"
WScript.ConnectObject Application, "on"
End If
i = 2
Do Until Cells(i, 1) = ""
session.findById("wnd[0]").maximize
session.findById("wnd[0]/usr/ctxtGV_MATNR").Text = Cells(i, 1)
session.findById("wnd[0]/usr/ctxtGV_WERKS").Text = Cells(i, 2)
session.findById("wnd[0]/usr/ctxtGV_WERKS").SetFocus
session.findById("wnd[0]/usr/ctxtGV_WERKS").caretPosition = 4
session.findById("wnd[0]").sendVKey 0
session.findById("wnd[0]/usr/txtZIP_MM02_STRUCTURE-EISBE_P").Text = Cells(i, 3)
session.findById("wnd[0]/usr/ctxtZIP_MM02_STRUCTURE-EISBE_RD").Text = Cells(i, 4)
session.findById("wnd[0]/usr/ctxtZIP_MM02_STRUCTURE-EISBE_RD").SetFocus
session.findById("wnd[0]/usr/ctxtZIP_MM02_STRUCTURE-EISBE_RD").caretPosition = 10
session.findById("wnd[0]/usr/ctxtZIP_MM02_STRUCTURE-EISBE_RD").caretPosition = 10
session.findById("wnd[0]/tbar[1]/btn[21]").press
session.findById("wnd[0]/usr/cntlTEXTEDIT/shellcont/shell").Text = Cells(i, 5) + vbCr + "" + vbCr + ""
session.findById("wnd[0]/usr/cntlTEXTEDIT/shellcont/shell").setSelectionIndexes 99, 99
session.findById("wnd[0]/tbar[0]/btn[11]").press
i = i + 1
Loop
End Sub
Problem with your solution is that the control showing table wont let you access basicaly anything further than what is visible (not actually true, another 3 or so rows may be loaded into memory though).
What you need to do is to refresh the table either by using the "Next Page (Page down)" button from the upper bar of SAP GUI or manipulate the scrollbar.
Either way, remember that the row index will reset back to the beginning so you would need to reset your counter too.
You may find it easier to not contain all the code in On Error Resume Next too.
Example for one of the kinds of shell tables:
For i = 0 To session.findById("wnd[0]/shellcont/shell").rowcount - 1
session.findById("wnd[0]/shellcont/shell").firstVisibleRow = i
Next
So I have a macro that updates prices in SAP GUI. It copies cell by cell and does the update order by order, but some times, right after performing the update and saving the order to go with the next line, a prompt appears in SAP where I need to click Yes or No, or Accept / Reject.
My macro then stops as it does not have a line of code to act on it. I do know which line is required, but my question is how to I write a line of code which would be executed if the prompt appears?
Keep in mind that sometimes it pops up and sometimes it does not.
Here is my code:
Public sessioninfo As SAPFEWSELib.GuiSessionInfo
Public Sub fastPFI()
Dim ws As Worksheet
Dim App As SAPFEWSELib.GuiApplication
Dim sor As Long
Dim maxsor As String
'HOEEUBV2 (EUB with scripting)
Set GuiAuto = GetObject("SAPGUI") 'Get the SAP GUI Scripting object
Set App = GuiAuto.GetScriptingEngine 'Get the currently running SAP GUI
Set Con = App.Children(0) 'Get the first system that is currently connected
Set session = Con.Children(0) 'Get the first session (window) on that connection
Set sessioninfo = session.Info
Set ws = Excel.ThisWorkbook.Worksheets("system")
sor = 2
maxsor = ws.Cells(Rows.Count, 1).End(xlUp).Row
'maxsor = 3
Do While sor < maxsor + 1
session.StartTransaction "va02"
'session.FindById("wnd[0]").SendVKey 0
session.FindById("wnd[0]/usr/ctxtVBAK-VBELN").Text = Cells(sor, 1)
session.FindById("wnd[0]").SendVKey 0
session.FindById("wnd[1]").SendVKey 0
session.FindById("wnd[0]").SendVKey 30
session.FindById("wnd[0]").SendVKey 11
session.FindById("wnd[0]/usr/lblRV45S-BSTNK").SetFocus
session.FindById("wnd[0]/usr/lblRV45S-BSTNK").CaretPosition = 18
'session.FindById("wnd[0]").SendVKey 0
sor = sor + 1
Loop
MsgBox "All proformas have been created" & vbNewLine & "Click OK to close file"
' Application.DisplayAlerts = False
'ActiveWorkbook.Close Savechanges:=False
'Application.DisplayAlerts = True
End Sub```
On Error GoTo Next after the line of code which could or not happen solved it.
I'm trying to write a macro. The macro is supposed to work by the user clicking on the first empty cell in column D. Then it should grab the tracking number to the left in column C. Navigate to the website. Return the delivered date into the first clicked on cell, then basically shift down one row and do the same thing without having to click again on the next row. Loop the process until you encounter the first emtpy cell in column C. This can't start at a particular cell every time because it's an on going spread sheet that's added too every week and this will start close the the bottom. For instance this week where I started was cell D2343. It's not finished code, but any suggestions would be helpful. I am fairly new to coding and extremely new to excel VBA so please bear with me. There's probably a better way to go about this than using activecell, but I'm not sure how. This
Public Sub Tracking()
Dim IE As Object
Dim ReturnValue As String
Dim ProUrl As String
Dim RowCount As Integer
Set IE = CreateObject("InternetExplorer.application")
RowCount = 0
'THIS LINE RETURN THE ERROR
Do While Not ActiveCell.Offset(-1, RowCount).Value = ""
ProUrl = "https://www.rrts.com/Tools/Tracking/Pages/MultipleResults.aspx?PROS=" & ActiveCell.Offset(-1, RowCount).Value
With IE
.Visible = False
.Navigate ProUrl
Do Until Not IE.Busy And IE.readyState = 4: DoEvents: Loop
End With
ReturnValue = Trim(IE.document.getElementsByTagName("Span")(16).innerText)
ActiveCell.Offset(, RowCount).Value = ReturnValue
RowCount = RowCount + 1
Loop
IE.Quit
Set IE = Nothing
End Sub
Any help would be appreciated. Stackoverflow has been a tremendous resource. Thank you.
I think the error may be in your Offset method. The first argument should be the row offset, and the second argument should be the column offset. It seems like you may have that backwards.
Try changing it to:
Do While Not ActiveCell.Offset(RowCount, -1).Value = ""
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Thank you in advance for the help.
When I run tickers through the code it stops. This is pulling mutual fund data, so if you want to test the code yourself...I would Use(INDZX, CULAX, ABRZX, TAGBX, PRPFX (Don't use these Mutual funds, they are no good; just for an example)). I literally have to sit by my computer and erase the tickers where the data has already been pulled over so that it can start over again; very time consuming.
Can one of you please help me out.
Let me know if you have further questions on this.
Just to add when it completely breaks, and look at the debug, it highlights the "Do While IE.readystate<> 4: DoEvents: Loop
The other issue I am having is that when there are no tickers left, the code continues to run.
Sub upDown()
Dim IE As Object, Doc As Object, lastRow As Long, tblTR As Object, tblTD As Object,
strCode As String
lastRow = Range("H65000").End(xlUp).Row
Set IE = CreateObject("internetexplorer.application")
IE.Visible = True
last_row = Sheets("Tickers").Range("H1").End(xlDown).Row
ini_row_dest = 1
Sheets("upDown").Select
Sheets("upDown").Range("A1:m10000").ClearContents
Application.ScreenUpdating = True
For i = 1 To lastRow
Application.StatusBar = "Updating upDown" & i & "/" & last_row
row_dest = ini_row_dest + (i - 1)
strCode = "Tickers" ' Range("A" & i).value
list_symbol = Sheets("Tickers").Range("h" & i)
IE.navigate "http://performance.morningstar.com/fund/ratings-risk.action?t=" & list_symbol
Do While IE.readystate <> 4: DoEvents: Loop
Set Doc = CreateObject("htmlfile")
Set Doc = IE.document
tryAgain:
Set tblTR = Doc.getelementbyid("div_upDownsidecapture").getelementsbytagname("tr")(3)
If tblTR Is Nothing Then GoTo tryAgain
On Error Resume Next
j = 2
For Each tblTD In tblTR.getelementsbytagname("td")
tdVal = Split(tblTD.innerText, vbCrLf)
Cells(i, j) = tdVal(0)
Cells(i, j + 1) = tdVal(1)
j = j + 2
Next
Sheets("upDown").Range("A" & row_dest).Value = list_symbol
Next i
Range("A3").Select
Application.StatusBar = False
Application.Calculation = xlAutomatic
End Sub
From your description, when it's 'stuck' you press CTRL-Break, and it stops at
Do While IE.readystate<> 4: DoEvents: Loop
This means that IE is busy. You should probably work out why. What happens if you switch to the IE window? Maybe it has a popup? It's entirely likely that morningstar.com has detected that you are scraping data and is halting it. Normally you need to pay some kind of a subscription to get this kind of thing.
Anyway what you could do is put in a 'watchdog' that detects this state and tries to recover. Here is some code below but it is basically a hack and I don't quite understand how your row index is meant to work. The code below uses Goto which is just a lazy way of doing things but it is certainly no worse than the existing code.
Anyway try it and see. What you might find is that the IE.Quit line might prompt you to close IE, but at least it can restart from where it failed and you don't need to clear the tickers out and start again.
An alternative solution might be to save the half finished workbook and alter the code to pick up from where it left off based on which tickers have data and which don't
Sub upDown()
Dim IE As Object, Doc As Object, lastRow As Long, tblTR As Object, tblTD As Object,
strCode As String
Dim iWatchDog as Integer
iWatchDog = 1
lastRow = Range("H65000").End(xlUp).Row
ini_row_dest = 1
Sheets("upDown").Select
Sheets("upDown").Range("A1:m10000").ClearContents
Start:
Set IE = CreateObject("internetexplorer.application")
IE.Visible = True
last_row = Sheets("Tickers").Range("H1").End(xlDown).Row
Application.ScreenUpdating = True
For i = 1 To lastRow
Application.StatusBar = "Updating upDown" & i & "/" & last_row
row_dest = ini_row_dest + (i - 1)
strCode = "Tickers" ' Range("A" & i).value
list_symbol = Sheets("Tickers").Range("h" & i)
IE.navigate "http://performance.morningstar.com/fund/ratings-risk.action?t=" & list_symbol
Do While IE.readystate <> 4
DoEvents
DoEvents
DoEvents
DoEvents
DoEvents
iWatchDog = iWatchDog + 1
If iWatchDog >= 10000 Then
Application.StatusBar = "Stuck - resetting"
iWatchDog = 1
IE.Stop
IE.Quit
Set IE = Nothing
DoEvents
DoEvents
DoEvents
DoEvents
Goto Start
End If
Loop
Set Doc = CreateObject("htmlfile")
Set Doc = IE.document
tryAgain:
Set tblTR = Doc.getelementbyid("div_upDownsidecapture").getelementsbytagname("tr")(3)
If tblTR Is Nothing Then GoTo tryAgain
On Error Resume Next
j = 2
For Each tblTD In tblTR.getelementsbytagname("td")
tdVal = Split(tblTD.innerText, vbCrLf)
Cells(i, j) = tdVal(0)
Cells(i, j + 1) = tdVal(1)
j = j + 2
Next
Sheets("upDown").Range("A" & row_dest).Value = list_symbol
Next i
Range("A3").Select
Application.StatusBar = False
Application.Calculation = xlAutomatic
End Sub
Where is this 3,800 lines of ticker data eventually going? into a database or is it fed into another Excel sheet?
This script is to reset a template, by copying a hidden worksheet template and deleting the existing sheet (after repopulating some reference data). I have tested it and it runs fine in debugging mode.
Option Explicit
Sub reset_PrintLayout_byCopy()
'the script replace the used printlayout with a copy from the hidden master.
Dim MeetingData() As String
Dim i As Integer
Dim j As Integer
Dim currentSheet As String
Dim datacolumns() As String
Dim userConfirm As String
ReDim Preserve MeetingData(3, 2)
ReDim Preserve datacolumns(2)
'warning about deleting data
userConfirm = MsgBox(Prompt:="Resetting the template will erase all data on the " _
& "PrintLayout Template. Choose ""Cancel"", if you wish to save the file first", _
Buttons:=vbOKCancel, Title:="Data to be erased!")
If (userConfirm = vbCancel) Then
Exit Sub
End If
'set parameters
datacolumns(0) = "D1"
datacolumns(1) = "I1"
'stop screen updating and displaying warnings
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'set active sheet
currentSheet = ActiveSheet.Name
'capture meeting data already filled out
For j = 0 To UBound(datacolumns) - 1
For i = 1 To 3
If Worksheets(currentSheet).Cells(i, Range(datacolumns(j)).Column).Value <> "" Then
MeetingData(i - 1, j) = Worksheets(currentSheet).Cells(i, Range(datacolumns(j)).Column).Value
End If
Next i
Next j
'make hidden template visible
Worksheets("hiddenPrintLayoutTemplate").Visible = True
'Rename current Sheet
Sheets(currentSheet).Name = "used_Print_Layout"
''add a new sheet
' ActiveWorkbook.Worksheets.Add(before:=Sheets("used_Print_Layout")).Name = "PrintLayout Template"
'copy hiddentemplate before current sheet
Worksheets("hiddenPrintLayoutTemplate").Copy before:=Sheets("used_Print_Layout")
ActiveSheet.Name = currentSheet
'set rowheight for title rows
Range("A12").EntireRow.RowHeight = 24
Range("A18").EntireRow.RowHeight = 24
'delete current used printlayout
Worksheets("used_Print_Layout").Delete
'refilled meeting data
For j = 0 To UBound(datacolumns) - 1
For i = 1 To 3
If MeetingData(i - 1, j) <> "" Then
Worksheets(currentSheet).Cells(i, Range(datacolumns(j)).Column).Value = MeetingData(i - 1, j)
End If
Next i
Next j
'hide PrintLayout template
'Worksheets("hiddenPrintLayoutTemplate").Visible = xlSheetVeryHidden
'Sheets("PrintLayout Template").Select
'activate screenupdating and display warnings
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
When run it in macro mode on button, it runs, but excel crashes, when it is done. I cannot find what the issue is. Any ideas?
I am not sure if by debugging you mean stepping through line by line, but you could try inserting stop statements at key points in the code. So for example, you could put a stop statement in the following part:
'capture meeting data already filled out
For j = 0 To UBound(datacolumns) - 1
For i = 1 To 3
If Worksheets(currentSheet).Cells(i, Range(datacolumns(j)).Column).Value <> "" Then
MeetingData(i - 1, j) = Worksheets(currentSheet).Cells(i,Range(datacolumns(j)).Column).Value
End If
Next i
Next j
stop
'make hidden template visible
Worksheets("hiddenPrintLayoutTemplate").Visible = True
You could see if the code runs fine up until that point (i.e. run it without debugging). If it does, remove the stop statement and place it further down the code. Repeat this until you find the statements which cause your crash - perhaps the reason would appear then.
In general, if you get an odd crash in Excel VBA, try switching the Windows default printer to Microsoft XPS Document Writer. Seems odd, but that has worked for me on problems where I've wasted many hours only to find this is the culprit.