Bài viết: SAP Scripting – Excel và SAP (P2)

kyo

Nguyễn Khắc Duy
Thành viên BQT
Administrator
Tham gia ngày
4 Tháng sáu 2006
Bài viết
900
Thích
2,599
Điểm
910
#1
SAP Scripting - Excel và SAP (P2)


Phần 2: Chỉnh sửa Script và đưa vào file Excel



Trong phần 1 trước, tôi đã giúp bạn hình thành 1 đoạn script cơ bản bằng chức năng Script Recording của SAP. Bây giờ, tôi sẽ dùng chính file script này để giúp bạn cách chỉnh sửa và đưa vào file Excel của bạn nhé. Bạn có thể quay về phần 1 tại đây để lấy script nhằm thực hành cho phần 2 này.

Đây là script của lần trước và tôi đã ghi chú lại một chút để bạn có thể hiểu trực tiếp trong script luôn.

Mã:
'Đoạn code này dùng để kết nối với SAP.
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
'-----------
session.findById("wnd[0]").maximize 'Dòng code này để phóng to màn hình SAP
session.findById("wnd[0]/tbar[0]/okcd").text = "mm02" 'Nhập t-code mm02
session.findById("wnd[0]").sendVKey 0 ‘Đại diện cho phím Enter
session.findById("wnd[0]/usr/ctxtRMMG1-MATNR").text = "P11220169" 'Nhập mã NVL vào ô
session.findById("wnd[0]").sendVKey 0 ‘Nhấn Enter
session.findById("wnd[1]/usr/tblSAPLMGMMTC_VIEW").getAbsoluteRow(14).selected = true 'Chọn dòng số 14 trong bảng mới hiện ra sau khi Enter
session.findById("wnd[1]/usr/tblSAPLMGMMTC_VIEW/txtMSICHTAUSW-DYTXT[0,14]").setFocus
session.findById("wnd[1]/usr/tblSAPLMGMMTC_VIEW/txtMSICHTAUSW-DYTXT[0,14]").caretPosition = 0
session.findById("wnd[1]").sendVKey 0 ‘Nhấn Enter
session.findById("wnd[1]/usr/ctxtRMMG1-WERKS").text = "VN11" 'Nhập VN11 vào cửa sổ hiện ra, ô thứ nhất
session.findById("wnd[1]/usr/ctxtRMMG1-LGNUM").text = "VMR" 'Tương tự nhập tiếp VMR
session.findById("wnd[1]/usr/ctxtRMMG1-LGTYP").text = "TWB" 'Nhập TWB
session.findById("wnd[1]/usr/ctxtRMMG1-LGTYP").setFocus
session.findById("wnd[1]/usr/ctxtRMMG1-LGTYP").caretPosition = 3
session.findById("wnd[1]/tbar[0]/btn[0]").press 'Nhấn chọn dấu kiểm đồng ý
session.findById("wnd[0]/usr/tabsTABSPR1/tabpSP22/ssubTABFRA1:SAPLMGMM:2000/subSUB2:SAPLMGD1:2732/txtMLGN-LHMG1").text = "4000" 'Nhập số 4000 vào ô LE Quantity
session.findById("wnd[0]/usr/tabsTABSPR1/tabpSP22/ssubTABFRA1:SAPLMGMM:2000/subSUB2:SAPLMGD1:2732/txtMLGN-LHMG1").setFocus
session.findById("wnd[0]/usr/tabsTABSPR1/tabpSP22/ssubTABFRA1:SAPLMGMM:2000/subSUB2:SAPLMGD1:2732/txtMLGN-LHMG1").caretPosition = 17
session.findById("wnd[0]/tbar[0]/btn[11]").press 'Nhấn nút Save ở phía trên để lưu
Khá dễ hiểu đúng không? Gần như tất cả mọi thao tác bạn thực hiện đều đã được ghi lại, y hệt như bạn ghi một macro trong Excel. Do đó, một cách tương tự, nếu bạn cảm thấy bạn đã quên một điều gì đó (đó có thể là do những thiết lập mặc định trong máy tính của bạn) và bạn mong muốn có 1 script tổng quát hơn, bạn nên ghi lại một script mới với một kịch bản tổng quát nhất để sau đó chúng ta tiến hành điều chỉnh nhằm tăng độ linh hoạt của script này.

Bây giờ, bạn mở Excel, vào VBA, tạo một module mới, sub mới và copy tất cả đoạn trên vào module như sau. Bạn lưu ý trên hình có 4 chỗ tôi khoanh đỏ, bạn nên thêm chữ s đằng trước Application như tôi để tạo thành 1 biến mới.



Vậy là bây giờ bạn đã có một macro hoàn chỉnh rồi đấy. Bạn thử bấm Play xem, macro này sẽ giúp bạn thực hiện những gì bạn đã làm trên SAP từ nãy giờ thông qua Excel.

Tuy nhiên, cái chúng ta muốn chính là chỉnh sửa 100 mã vật tư khác nhau, do đó bạn cần phải chỉnh sửa thêm trong code này vì nếu bạn giữ như vậy, nó sẽ chỉ làm giúp bạn duy nhất 1 mã mà thôi (tương tự như macro khi bạn ghi trong Excel, bạn cũng cần chỉnh sửa để nó thực hiện được linh hoạt).

Đầu tiên, chắc chắn rồi, bạn nên có một khung mẫu. Ở đây, tôi giả sử vật tư tôi cần sẽ ở cột A và giá trị khối lượng LE sẽ ở cột B.



Sau đó, tôi sẽ vào code và chỉnh sửa lại như dưới đây:

Mã:
Sub Edit_LEQuantity()
 
Dim i As Long, EndR As Long
 
If Not IsObject(sApplication) Then
   Set SapGuiAuto = GetObject("SAPGUI")
   Set sApplication = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(Connection) Then
   Set Connection = sApplication.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 sApplication, "on"
End If
 
EndR = Sheet1.Range("A65000").End(xlUp).Row
 
session.findById("wnd[0]").maximize
session.findById("wnd[0]/tbar[0]/okcd").Text = "mm02"
session.findById("wnd[0]").sendVKey 0
 
For i = 2 To EndR
    session.findById("wnd[0]/usr/ctxtRMMG1-MATNR").Text = Sheet1.Range("A" & i).Value
    session.findById("wnd[0]").sendVKey 0
    session.findById("wnd[1]/usr/tblSAPLMGMMTC_VIEW").getAbsoluteRow(14).Selected = True
    session.findById("wnd[1]/usr/tblSAPLMGMMTC_VIEW/txtMSICHTAUSW-DYTXT[0,14]").SetFocus
    session.findById("wnd[1]/usr/tblSAPLMGMMTC_VIEW/txtMSICHTAUSW-DYTXT[0,14]").caretPosition = 0
    session.findById("wnd[1]").sendVKey 0
    session.findById("wnd[1]/usr/ctxtRMMG1-WERKS").Text = "VN11"
    session.findById("wnd[1]/usr/ctxtRMMG1-LGNUM").Text = "VMR"
    session.findById("wnd[1]/usr/ctxtRMMG1-LGTYP").Text = "TWB"
    session.findById("wnd[1]/usr/ctxtRMMG1-LGTYP").SetFocus
    session.findById("wnd[1]/usr/ctxtRMMG1-LGTYP").caretPosition = 3
    session.findById("wnd[1]/tbar[0]/btn[0]").press
    session.findById("wnd[0]/usr/tabsTABSPR1/tabpSP22/ssubTABFRA1:SAPLMGMM:2000/subSUB2:SAPLMGD1:2732/txtMLGN-LHMG1").Text = Sheet1.Range("B" & i).Value
    session.findById("wnd[0]/usr/tabsTABSPR1/tabpSP22/ssubTABFRA1:SAPLMGMM:2000/subSUB2:SAPLMGD1:2732/txtMLGN-LHMG1").SetFocus
    session.findById("wnd[0]/usr/tabsTABSPR1/tabpSP22/ssubTABFRA1:SAPLMGMM:2000/subSUB2:SAPLMGD1:2732/txtMLGN-LHMG1").caretPosition = 17
    session.findById("wnd[0]/tbar[0]/btn[11]").press
Next i
 
MsgBox "Done"
End Sub
Bạn có nhận thấy sự khác biệt không? Tôi đã lồng thêm một vòng lặp và cho code lấy dữ liệu của từng ô trong cột A và B để điền vào vị trí của mã P và số lượng 4000 từ đợt ghi trước. Bây giờ việc tiếp theo chỉ là làm một nút chọn để kích hoạt macro này mà thôi.

Vậy là từ giờ phút này, bạn chỉ việc bật SAP và file Excel này, sau đó chạy macro là các mã vật tư của bạn sẽ tự thay đổi tuần tự trên Excel một cách dễ dàng.

Dĩ nhiên, code này vẫn còn nhiều hạn chế do chúng ta chỉ mới tập sửa chữa tại chỗ nhập của SAP chứ vẫn chưa tìm hiểu kỹ về giao diện, tương tác của SAP cũng như các chiến lược đối phó với những rủi ro bất ngờ như cửa sổ thông điệp bỗng nhiên hiện ra, hay thiết lập Warehouse Management 2 của script trước vẫn đang bị cố định ở hàng số 14 mà sẽ có nhiều mã, thiết lập này ở hàng 13, hay hàng 10 hoặc thậm chí không có. Và đó sẽ là chủ đề cho phần tiếp theo bạn nhé.

Chúc bạn thành công!

Một số bài viết có liên quan:
1/ SAP Scripting - Excel và SAP (P1)
2/ PivotTable trong Excel 2010 - 2013
3/ Highlight hàng khi di chuyển chuột
4/ Sử dụng các nút điều khiển (Form Controls) trong một bảng tính
5/ Thủ thuật sử dụng tên ở vùng giao nhau của hai dãy
6/ Tổng hợp dữ liệu trên nhiều bảng tính
7/ Công cụ Camera trong Excel
8/ Mật khẩu và bảo mật trong Excel
9/ Excel nâng cao: Sử dụng sự lặp lại và các tham chiếu tuần hoàn
10/ 10 lý do để học công thức Excel
 

File đính kèm

Lần chỉnh sửa cuối:

levanduyet

Thành viên gắn bó
Thành viên danh dự
Tham gia ngày
30 Tháng năm 2006
Bài viết
1,781
Thích
4,465
Điểm
860
#2
Có một cách khác để làm việc với SAP là sử dụng Autoit.
Trong đoạn mã sau có sử dụng SAP.au3.
Đoạn mã thể hiện việc đăng nhập SAP, vào MB52 và lấy dữ liệu lưu ra tập tin Excel.
Với ý tưởng của Duy, chỉ việc thêm phần làm việc với tập tin Excel, lấy dữ liệu từ tập tin Excel và cập nhật dữ liệu SAP.
Ví dụ: tôi muốn cập nhật tên các sản phẩm tương ứng với mỗi mã hàng trong SAP.
[GPECODE=applescript]
#include-once
#include <GuiConstants.au3>
#include <SAP.au3>
#include <DateTimeConstants.au3>

#Region to test these UDF
; Date amended: 10/06/2010, Sinh Nhat Bac Luyen
; Autoit Set options
;2 = relative coords to the client area of the active window
;AutoItSetOption("MouseCoordMode",2)
; Logon to SAP
; Run the saplogon.exe
; At the folder C:\Program Files\SAP\FrontEnd\SapGui
; You should change the path according to your

;Chose date before doing anything
$sNewDate = _ChoseDate()
if $sNewDate=0 Then
Exit
Else
$sNewDate=StringReplace($sNewDate, "/", ".")
EndIf

ShellExecute("saplogon.exe", "", "C:\Program Files\SAP\FrontEnd\SapGui")
; Check error
; If there is error then exit
if @error<>0 then
MsgBox(0,"Inf","Please check your SAP file location.")
Exit
EndIf

Sleep(1000)

; Waiting for the Sreen "SAP Logon 640" was shown
WinActivate("SAP Logon 640")
; Check Window "SAP Logon 640" again
; to make sure everything is OK
if @error<>0 then
MsgBox(0,"Inf","Please check your SAP version.")
Exit
EndIf

Sleep(1000)

; Click on the Log on button
; i.e send Alt + l key
Send("!l")

; Waiting for the sreen "SAP" was shown
WinActivate("SAP")
if @error<>0 then
MsgBox(0,"Inf","You need to check your shortcut Alt + l.")
Exit
EndIf

;Logon to SAP

; Cach 1 - Hay hon
_SAPSessAttach("SAP")

; WINXP
;/app/con[0]/ses[0]/wnd[0]/usr/txtRSYST-MANDT
;_SAPObjValueSet("usr/txtRSYST-MANDT","117")

; WIN VISTA
;/app/con[0]/ses[0]/wnd[0]/usr/txt[0]
; Gan gia tri 117 vao truong Client
_SAPObjValueSet("usr/txt[0]", "117")

; WINXP
;/app/con[0]/ses[0]/wnd[0]/usr/txtRSYST-BNAME
;_SAPObjValueSet("usr/txtRSYST-BNAME","00008381")

; WIN VISTA
;/app/con[0]/ses[0]/wnd[0]/usr/txt[1]
; Gan User ID vao truong User
_SAPObjValueSet("usr/txt[1]", "00008381")

; WINXP
;/app/con[0]/ses[0]/wnd[0]/usr/pwdRSYST-BCODE
;_SAPObjValueSet("usr/pwdRSYST-BCODE","Nhan2007")

; WIN VISTA
;/app/con[0]/ses[0]/wnd[0]/usr/pwd
; Update 04/05/2010
; Gan password vao truong Password
_SAPObjValueSet("usr/pwd", "Duyet2007")

; After Enter everything
; then send key Enter
Send("{ENTER}")
Sleep(1000)
;Waiting for the sreen "SAP Easy Access"
WinActivate("SAP Easy Access")

if @error<>0 then
MsgBox(0,"Inf","There is error in your script, line 158")
Exit
EndIf
; Before running this script, ensure the "SAP Easy Access" window is open.
; Attach to the session with the window titled "SAP Easy Access"
_SAPSessAttach("SAP Easy Access")

; Put the value "/nmb51" into the command field.
_SAPObjValueSet("tbar[0]/okcd", "/nmb51")

; Press the "Enter" key.
_SAPVKeysSend("Enter")
; Set some fields
;/app/con[0]/ses[0]/wnd[0]/usr/ctxt[4] Location: W001
_SAPObjValueSet("usr/ctxt[4]", "W001")
;/app/con[0]/ses[0]/wnd[0]/usr/ctxt[12] Movement Type 1: 601
;/app/con[0]/ses[0]/wnd[0]/usr/ctxt[13] Movement Type 2: 602
_SAPObjValueSet("usr/ctxt[12]", "601")
_SAPObjValueSet("usr/ctxt[13]", "602")

;/app/con[0]/ses[0]/wnd[0]/usr/ctxt[16] Post date:


;Chose date, first method
;
;$value = InputBox("Chon ngay", "Ban chon may ngay truoc ngay hien tai?", "1", " M2")
;If @Error<>0 Then
; Exit
;EndIf
;$lDate=Number($value)
;$value=(-1)*$lDate
;$sNewDate = _DateAdd( 'd',$value, _NowCalcDate())
;$sNewDate=_DateTimeFormat($sNewDate, 2)
;$sNewDate=StringReplace($sNewDate, "/", ".")

;Chose date, second method
;

;$sNewDate = _ChoseDate()
;if $sNewDate=0 Then
; Exit
;Else
; $sNewDate=StringReplace($sNewDate, "/", ".")
;EndIf

;MsgBox( 4096, "", "Date you want is " & $sNewDate )
_SAPObjValueSet("usr/ctxt[16]", $sNewDate)
; Press Enter then F8 to run this T-Code
_SAPVKeysSend("Enter")
_SAPVKeysSend("F8")
; Waiting for the sreen "Display warehouse stocks of material"
;WinActivate("Display Warehouse Stocks of Material")
;if @error<>0 then
; MsgBox(0,"Inf","There is error in your script.")
; Exit
;EndIf
; Press button to change the details
;
_SAPVKeysSend("Ctrl+Shift+F12")
; Press button to extract in excel format
_SAPVKeysSend("F9")
WinWait("Save list in file...")
if not WinActivate("Save list in file...") Then
WinActivate("Save list in file...")
EndIf
WinWaitActive("Save list in file...")
$size = WinGetPos("Save list in file...")
MouseMove($size[0]+$size[2]/2,$size[1]+$size[3]/2)
if @error<>0 then
MsgBox(0,"Inf","There is error in your script.")
Exit
EndIf
Sleep(1000)
;$size = WinGetPos("Save list in file...")
;MsgBox(0, "Active window stats (x,y,width,height):", $size[0] & " " & $size[1] & " " & $size[2] & " " & $size[3])
_SAPSessAttach("Save list in file...")
;_SAPObjSelect("usr/subSUBSCREEN_STEPLOOP:SAPLSPO5:0150/sub:SAPLSPO5:0150/radSPOPLI-SELFLAG[1,0]")
;/app/con[0]/ses[0]/wnd[1]/usr/sub/2/sub/2/1/rad[1,0]
_SAPObjSelect("usr/sub/2/sub/2/1/rad[1,0]")
_SAPVKeysSend("Enter")
;-------------------------------------------
;/app/con[0]/ses[0]/wnd[1]/usr/sub:SAPLSPO5:0201/radSPOPLI-SELFLAG[1,0]
;Send("{DOWN}")
;_SAPObjSelect("usr/sub:SAPLSPO5:0201/radSPOPLI-SELFLAG[1,0]")
;_SAPObjValueSet("usr/sub:SAPLSPO5:0201/radSPOPLI","1")
;Press Enter
;_SAPSessAttach("Material Document List")
;_SAPVKeysSend("Enter")
; Sometimes this _SAPVKeysSend is not correct, check later
Send("{ENTER}")
Sleep(1000)
;Waiting for the sreen "Material Document List"
;MouseMove(100,0)
;MouseMove(600,0)
WinWait("Material Document List")
if not WinActivate("Material Document List") Then
WinActivate("Material Document List")
EndIf
WinWaitActive("Material Document List")
$size = WinGetPos("Material Document List")
MouseMove($size[0]+$size[2]/2,$size[1]+$size[3]/2)
;MsgBox(0,"Inf","Material Document List window is active.")
if @error<>0 then
MsgBox(0,"Inf","The window Material Document List does not exist.")
Exit
EndIf

;MsgBox(0, "Active window stats (x,y,width,height):", $size[0] & " " & $size[1] & " " & $size[2] & " " & $size[3])
; WINXP
; Set the File Name
;_SAPObjValueSet("usr/ctxtDY_FILENAME", "Stock_Temp.xls")

; WIN VISTA
; Date: 5/5/2010
; /app/con[0]/ses[0]/wnd[1]/usr/ctxt[1]
;/app/con[0]/ses[0]/wnd[1]/usr/ctxt[1]: File name
_SAPObjValueSet("usr/ctxt[1]", "DN_Temp.xls")
; Press the button Replace
; /app/con[0]/ses[0]/wnd[1]/tbar[0]/btn[11]
; Press button
_SAPObjSelect("tbar[0]/btn[11]")

; Waiting for the sreen "Material Document List"
WinActivate("Material Document List")
if @error<>0 then
MsgBox(0,"Inf","There is error in your script.")
Exit
EndIf
;$size = WinGetPos("Material Document List")
;MsgBox(0, "Active window stats (x,y,width,height):", $size[0] & " " & $size[1] & " " & $size[2] & " " & $size[3])
_SAPSessAttach("Material Document List")

;/app/con[0]/ses[0]/wnd[0]/tbar[0]/okcd
;
_SAPObjValueSet("tbar[0]/okcd", "/nend")
;Press Enter
_SAPVKeysSend("Enter")
WinWait("Log Off")
if not WinActivate("Log Off") Then
WinActivate("Log Off")
EndIf
WinWaitActive("Log Off")
$size = WinGetPos("Log Off")
MouseMove($size[0]+$size[2]/2,$size[1]+$size[3]/2)
if @error<>0 then
MsgBox(0,"Inf","There is error in your script, line 2242")
Exit
EndIf

_SAPSessAttach("Log Off")
Sleep(1000)
;/app/con[0]/ses[0]/wnd[1]/usr/btnSPOP-OPTION1
;_SAPObjSelect("usr/btnSPOP-OPTION1")

; Date: 5/5/2010
; /app/con[0]/ses[0]/wnd[1]/usr/btn[0]
_SAPObjSelect("usr/btn[0]")
;Send("{TAB}")
Send("{ENTER}")
WinWait("SAP Logon 640")
if not WinActivate("SAP Logon 640") Then
WinActivate("SAP Logon 640")
EndIf
WinWaitActive("SAP Logon 640")
WinClose("SAP Logon 640")
; This function to get the date from the user
Func _ChoseDate()
Dim $n, $msg, $button_1

GUICreate("Get the movements", 140, 100, 800, 200)
$n = GUICtrlCreateDate("", 20, 20, 100, 20, $DTS_SHORTDATEFORMAT)
; Create the controls
$button_1 = GUICtrlCreateButton("&OK", 20, 60, 100, 30)
GUISetState()

; In this message loop we use variables to keep track of changes to the radios, another
; way would be to use GUICtrlRead() at the end to read in the state of each control
While 1
$msg = GUIGetMsg()
Select
Case $msg = $GUI_EVENT_CLOSE
;This function will return 0 if the user does not want to run this
Return 0
GUIDelete()
Exit
Case $msg = $button_1
;Return the chosen date
Return GUICtrlRead($n)
GUIDelete()
exit
EndSelect
WEnd
EndFunc

#EndRegion to test these UDF


[/GPECODE]

Lê Văn Duyệt
 

kuldokk

Thành viên hoạt động
Tham gia ngày
12 Tháng mười 2007
Bài viết
149
Thích
159
Điểm
680
#3
Code VBA như ở #1 chỉ dùng trong trường hợp SAP GUI đã chạy rồi. Nếu SAP GUI chưa chạy thì còn phải kết nối/ đăng nhập với SAP GUI nữa.

Mã:
Sub sap_connect3()
    If Not IsObject(SapGuiApp) Then
        Set SapGuiApp = CreateObject("Sapgui.ScriptingCtrl.1")
    End If
    If Not IsObject(Connection) Then
        Set Connection = SapGuiApp.OpenConnectionByConnectionString("D02", False)
    End If
    If Not IsObject(session) Then
        Set session = Connection.Children(0)
    End If
    
    With session
        .findById("wnd[0]").maximize
        .findById("wnd[0]/usr/txtRSYST-MANDT").Text = "XXCLIENTXX"
        .findById("wnd[0]/usr/txtRSYST-BNAME").Text = "XXUSERXX"
        .findById("wnd[0]/usr/pwdRSYST-BCODE").Text = "XXPASSXX"
        .findById("wnd[0]/usr/txtRSYST-LANGU").Text = "DE"
        .findById("wnd[0]").sendVKey 0
    End with

'....
End Sub
 

majoson

Thành viên chính thức
Tham gia ngày
14 Tháng hai 2008
Bài viết
92
Thích
2
Điểm
0
#4
Xin chào,

Đây là section rất hữu ích. Mong ad tiếp tục từ cơ bản đến nâng cao các tương tác giữa SAP và Excel. Có thể có thêm các set up để lấy data trực tiếp từ SAP, đổ xuống excel (real time) và sau đó, xử lý trên excel và upload lại lên SAP. Vì SAP tính toán tốc độ chậm hơn và xử lý không nhanh như Excel.

Rất cám ơn chủ đề hữu ích này và mong nhận được phản hồi,
 
Tham gia ngày
9 Tháng mười 2012
Bài viết
2
Thích
1
Điểm
365
Tuổi
32
#5
Phần này quả thực rất hay.
E mong các anh chị đi trước đưa ra nhiều bài viết hay, đề cập đến sự tương tác giữa SAP và Excel.
Để các thành viên khác được học hỏi thêm.
 
Top