pb資料視窗技巧38個
1 使DataWindow列只能追加不能修改
如何使DataWindow中的資料只能追加新記錄而不能修改,利用 Column 的 Protect 屬性可以很方便的做到這一點,方法如下:將每一列的 Protect 屬性設定為:
If( IsRowNew(), 0, 1) )
在 PowerScript 中可以動態修改 Protect 屬性:
dw_1.Modify("column_name_here.Protect='1~tIf(IsRowNew(),0,1)'")
這樣,DataWindow 中只有新追加的記錄可修改,而其他記錄是隻讀的。
2 如何在DataWindow中實現列的自動折行
我們在PowerBuilder應用程式的開發過程中, 使用DataWindow時, 經常會遇
到某列的資料太長, 不能同時全部顯示的情況. 若採用自動水平滾動, 操作起
來又不夠簡便. 下面介紹一種方法, 實現列資料多行顯示, 即實現列資料的自
動折行.具體步驟如下:
1) 在DataWindow Painter中開啟此DataWindow.
2) 在需設定自動折行的列上雙擊滑鼠, 彈開此列的屬性視窗.
3) 選擇Position標籤, 選中Autosize Height 多選框.
4) 選擇Edit標籤, 不選中Auto Horz Scroll多選框.
5) 單擊OK按鈕, 儲存所做的修改.
6) 點中Detail Band (即寫有Detail的灰色長帶), 單擊滑鼠右鍵, 選擇
Properties... 選單項.
7) 選中Autosize Height多選框.
8) 單擊OK按鈕, 儲存所做的修改.
9) 儲存此DataWindow.
注意:
連在一起的漢字(中間沒有標點或空格分隔), 系統將認為是一個單詞, 不
會自動進行折行.
3 在資料視窗中實現動畫
要實現動畫,必須要有定時器,在資料視窗中已經有了一個定時器,雙擊資料視窗將彈出的對話方塊,在Timer Interval中定義大於零的值就有定時器(可以精確到毫秒),有了這個定時器就可以實現動畫了。比如要改變某欄位的背景顏色,可設
ackgound.color=RGB(Integer(Right(string(now(),'hhmmssf'),1))*256/10,Integer(Right(string(now(),'hhmmssf'),1))*256/10,0)
當然,您不僅可以改變背景顏色,而且可以改變字型等等任何屬性,使他可以動起來!
4 使資料視窗中的被選中行具有更好的外觀
大家都知道,在選擇資料視窗中的某一行時,如果使用pb提供的選擇函式SelectRow(),那麼的外觀真是不能恭維,單調而古板的藍色背景,可能和您的漂亮而生動的應用程式格格不入。有沒有辦法改變呢?當然有囉,請聽我慢慢道來。
改變某一行的背景比較簡單,改變每一列的背景屬性(backgroundcolor)即可,可要根據滑鼠選擇情況自動改變,並可以返回被選中的行可能還需要一定的技巧。下面分單行選擇和多行選擇分辨說明。
單行選擇
單行選擇比較簡單,我們只要將所有欄位的背景色的表示式改為:
if(GetRow()=CurrentRow(),RGB(255,126,0),RGB(0,0,0))
其中第一個顏色為被選中的顏色,第二個顏色未被選中的顏色。然後用GetRow()代替GetSelectedRow()函式來得到被選中的行。
多行選擇
多行選擇比較複雜,如果單純依靠改變資料視窗的屬性沒法實現,我們必須使用資料視窗屬性和程式碼結合起來才能實現
首先,改變資料視窗的SQL語句,增加一個計算欄位:0 as flag,Select 語句改為:
Select col1,col2 ,1 as flag from tablename where .....,
當返回資料視窗painter時,您就會發現多了一個欄位flag,我們就是利用這個欄位儲存行被選中的資訊。
其次,修改各個欄位的背景顏色屬性,設定為:if(flag=1,RGB(255,126,0),RGB(255,255,255))
第三:在資料視窗控制元件中,增加對clicked 事件的處理,程式碼如下:
if row<1 then return // setredraw(false)
if this.o b j e c t.flag[row]=1 then //如果該行被選中,撤銷選擇,否則選中該行
this.Object.flag[row]=0
else
this.Object.flag[row]=1
end if
setredraw(true)
您還可以定製本選中行的字型,文字屬性等等。原理相同,不再贅述。
5 將日期型欄位初始化為當天的日期
使用 Column Specifications 對話方塊來設定資料的初始值是一個比較好又比較通用的方法。為了將日期型欄位初始化為當天的日期,只要設定初始化值為today,而不是today()即可。同樣設定初始值為NUll,可以使用null,而不是 null()。
6 在DataWindow中調整列順序
在 Gird 風格的 DataWindow 中,列的排列順序是按照你選擇 Column 的順序排列的,並且不能改變.要改變列的順序則必須重新制作 DataWindow.
最近我發現一個辦法可以改變列的順序: 在 DataWindow 畫板中開啟要修改的 DataWindow,然後按 'Preview' 按鈕切換到預覽模式下,選擇要移動的列標題並拖動到預定位置,然後返回 DataWindow 畫板,存檔即可.
7 Retrieve時不清除原有Datawindow資料
當你呼叫Retrieve函式,PowerBuilder自動清除原有DataWindow然後Retrieve資料。在Datawindow RetrieveStart事件中,使用Return 2,這樣PowerBuilder不會清除原有資料而是追加新資料。
8 美化DataWindow的顯示效果
使DataWindow 的單雙行顯示顏色不同,不僅僅可以使你的應用程式更顯專業性,並使資料的可讀性增強。先調出你需要改動的DataWindow,在Detail band按下右鍵選擇Properties,選擇Tab頁中的Expressions,在color屬性中輸入下面內容:(注意是在Detail明細顯示段按右鍵,而不是在Column上) IF(MOD(GETROW(),2)=0,RGB(192, 192, 192), RGB(255, 255, 255)) 馬上Preview一下,看一看效果如何。
9 用Line建立漂亮的Grid DataWindow的技巧
雖然PowerBuilder有Grid風格的DataWindow,但不夠靈活,如果想列印一張邊框粗線條或雙線,內框為細線條的表格直接使用Grid風格的DataWindow就不能實現。因此許多人都用Tabular風格的DataWindow,然後自己用Line來實現Grid。在調整線條位置是一個即傷腦筋又傷眼睛的事件,而一旦需要調整行高,所有工作都得重來,試一試用下面方法,會大大減輕你的工作量: 在vertical lines,改變它的屬性,在Expressions Tab上,y1行上輸入0,y2行上輸入rowheight() - 1 在horizontal lines, 設定 y1 和 y2 = rowheight() - 5 這樣PowerBuilder會自動調整線的座標,你只需要設定橫線的長度和x1,x2的座標即可。馬上Preview一下,看一看效果! 你再也不需要因為行的高度發生改變而重新調整線條位置。
10 如何建立一個報表,如下形式
Quantity Running Total
5,000 5,000
2,500 7,500
3,000 10,500
12,000 22,500
對於Running Total列,我們可使用計算列:CumulativeSum(Quantity for all),即可達到逐漸遞增求和的功能。
11 資料視窗的資料送緩衝區之前確認的四個步驟判斷資料型別是否正確。如不正確則觸發ItemError事件。判斷資料是否符合有效性規則。如不符合有效性規則,同樣觸發ItemError事件。判斷是否有資料被改動。判斷資料是否通過ItemChanged事件,如果資料和ItemChanged相斥,將觸發ItemError事件。
12 如何在DataWindow中用資料型別為Datetime的列為條件進行查詢
1.當要查詢的日期條件是一常數時使用如下表達式:
ls_Find = "datetime_col
= DateTime ('1/1/1999')"
2.當要查詢的日期條件是一個變數時使用如下的表示式:
ls_Find = "datetime_col = DateTime ('" + ls_Date + "')"
3.當要查詢的日期條件是一個DateTime資料型別時使用如下表達式:
ls_Find = "datetime_col = DateTime ('" + String (ldt_DateTime) + "')"
13 設定資料視窗Boolean型屬性的三種方法
PowerBuilder提供了三種方法設定資料視窗的布林型屬性,分別是True/False, 1/0, 'Yes'/'No'。例如:
dw_1.Object.address.Visible = 0 dw_1.Object.address.Visible = False dw_1.Object.address.Visible = 'No'
PowerBuilder在處理上以字串的形式儲存屬性,而不考慮屬性值是布林型、長整型或是字元型。
為了進一步理解,可以匯出一個數據視窗並檢視它的原碼,可以發現即使是列的顏色屬性它也是使用帶雙引
號的數字來表達。
14 如何在DataWindow中快速刪除多行
在開發過程中可能經常有要進行多行刪除的操作,一般都使用迴圈語句進行操作:
FOR ll_RowOn = 1 TO dw_1.RowCount() dw_1.DeleteRow(ll_RowOn) NEXT
一個快速的刪除方法是把要刪除的行從主緩衝區中移到刪除緩衝區中。例如,刪除緩衝區中所有的行:
dw_1.RowsMove(dw_1, 1, dw_1.RowCount, Primary!, dw_1, 1, Delete!)
不過不要忘了過濾的行在不同的緩衝區中。
15 如何在DataWindow的SQL語法中不使用SELECT DISTINCT實現刪除重複的行
起先對你要顯示唯一值的列進行排序:"city A",然後增加如下過濾字串:" city < > city [-1] or GetRow () = 1"
16 如何在分組形式的DataWindow中分別顯示各組的行號
當我們為Datawindow的每一行顯示行號時,可以簡單的放一個表示式為GetRow()計算列。但是對於分組的Datawindow,要分別顯示各組的行號,則應使用表示式為
GetRow() - First(GetRow() for Group 1) + 1的計算列。
17 如何改變列的字型顏色,提醒使用者此列已做修改
在列的Color屬性中,輸入如下表達式
IF (column_name < >column_name.Original, RGB(255, 0, 0), RGB(0, 0, 0))。
在這個條件中,如果此列已改變,則顯示紅色字型,否則顯示黑色字型。這個表示式主要用column_name < > column_name.Original比較當前列的值和原始列的值是否相同來達到判斷的目的。
18 在資料視窗中移走行,但不是去做過濾或刪除操作
RowsDiscard()函式可做到這一點,它在資料視窗中執行移除工作,但被移走的行它不可被刪除或做任何修改性的儲存。
19 如何在多行顯示的DataWindow 中的Footer Band中顯示當前資料的首行和最後行的行號
我們先看兩個計算列的表示式: IF (GetRow() = First(GetRow() FOR Page), 1, 0) // 1 為當前頁的第一行
IF (GetRow() < > 1 AND GetRow() = Last(GetRow() FOR Page), 1, 0) // 1 為當前頁的最後一行
由上面可知,在Footer Band中設定如下計算列表達式:
'Rows ' + String(First(GetRow() FOR Page)) + ' to ' + String(Last(GetRow() FOR Page)) + ' are displayed'。
即可達到這項功能。
20 使可編輯的資料視窗只讀
有時,你可能需要將一個用於程式設計的資料視窗用作顯示目的,可以有以下幾種方法來實現這一要求:
1.建立兩個資料視窗,一個用於編輯,一個用於顯示
2.將資料視窗中的全部物件的taborder設定為0.
3.也可以將資料視窗中的列的protect屬性設為On或Off,但你不能使用protect屬性進行編輯操作
4.資料視窗有一個將datawindow設為只讀的屬性(readonly),使用它最方便。
21 資料視窗檢查重複行
dw_1.SetSort ("user_id A")
dw_1.Sort()
dw_1.SetFilter ("user_id = user_id[-1]")
dw_1.Filter()
if dw_1.RowCount() > 0 then
Messagebox("注意", "使用者編碼重複.")
end if
dw_1.SetFilter ("")
dw_1.Filter()
22 如何在分組形式的DataWindow中分別顯示各組的行號
---- 當我們為Datawindow的每一行顯示行號時,可以簡單的放一個表示式為GetRow()
---- 計算列。但是對於分組的Datawindow,要分別顯示各組的行號,則應使用表示式為
GetRow() - First(GetRow() for Group 1) + 1的計算列。
23 如何能讓資料視窗的某幾列在其他列橫拉時固定不動
////////////////////////////////////////////////////////////////
// 功能說明:用於凍結左邊的滾動欄
// 變更記錄: 變更或版本更新的時候
//
////////////////////////////////////////////////////////////////
int i
if pane = 1 then
i = integer(this.o b j e c t.datawindow.horizontalscrollposition2)
if i < 1 or isnull(i) then return
if scrollpos > 0 then
this.o b j e c t.datawindow.horizontalScrollPosition = 0
end if
else
i = integer(this.Object.DataWindow.HorizontalScrollSplit)
if i < 1 or isnull(i) then return
if i > scrollpos then
this.o b j e c t.datawindow.horizontalScrollPosition2 = i
end if
end if
24 在資料視窗中如果要使其中一列的屬性為只讀,也就是不允許使用者修改,那麼只需簡單地將這一列的Table Order 設定成0就可。然而,在有些情況下
需要對這一列的某些行修改,而某些行不能修改,這就要用到這一列的protect屬性了。開啟列的屬性中的Expressions,在protect中輸入條件判別
式。例如:允許使用者修改新增加的記錄,而檢索出來的記錄則不允許修改。條件判別式可以寫成如下:
if(isRowNew(),0,1)
在 PowerScript 中可以動態修改 Protect 屬性:
dw_1.Modify("column_name_here.Protect='1~tIf(IsRowNew(),0,1)'")
這樣,DataWindow 中只有新追加的記錄可修改,而其他記錄是隻讀的。
25 控制DATAWINDOW裡每頁顯示的行數
1、在Datawindow中增加一個計算域,起名為:ceil_page,此計算域必須放在Detail段中,
Expression中輸入 ceiling(getrow()/25) 25表示每頁列印25行,也可以是一個引數。
2、分組,選擇選單RowsCreate Group,選擇ceil_page
按ceil_page分組,並選中New Page On Group Break(意思是新組開始時換頁)。
3、將此計算域設為隱藏(在屬性頁中的expression頁中在visible屬性中寫0)。
4、補空行:
在視窗的open事件中寫如下程式碼:
long li_count,li_i
li_count=dw_1.retrieve()
if mod(li_count,25)<>0 then
for li_i=1 to 25 - mod(li_count,25)
dw_1.insertrow(0)
next
end if
26 資料視窗的closeQuery事件:提示儲存資料
dw_1.AcceptText()
IF dw_1.ModifiedCount() + dw_1.DeletedCount() > 0 THEN
CHOOSE CASE MessageBox("操作提示","資料已經發生變化,是否儲存?",Question!,YesNoCancel!,1)
CASE 1
cb_save.TriggerEvent(clicked!)
CASE 2
Return 0//不做任何操作直接關閉視窗
CASE 3
Return 1//不會執行Close Event,維持原來的情況
END CHOOSE
END IF
27 Getchild函式主要被用來得到一個數據視窗的子資料視窗
該函式在兩種情況下可以使用,1、取出資料視窗物件的下拉式資料視窗;
2、取出複合風格(composite)資料視窗物件裡所嵌入的子資料視窗物件。
語法:integer dwcontrol.GetChild (string name, REF DataWindowChild
dwchildvariable )
例子1 這段程式取出一個composite資料視窗物件的兩個子資料視窗,並對他們進行過濾,和排序的操作。
/*dw_dy是連線一個composite資料視窗物件的一個數據視窗控制元件。dw_1、dw_2分別是巢狀的資料視窗的NAME*/
String ls_filter
DataWindowChild dwc_czrw,dwc_czx//定義子資料視窗變數
dw_dy.Settranso b j e c t(sqlca)
dw_dy.Retrieve()
dw_dy.GetChild("dw_2",dwc_czrw)
dw_dy.Getchild("dw_1",dwc_czx)
ls_filter = "czrw_bh = '"+dw_3.GetItemString(dw_3.GetRow(),"czrw_bh")+"'"//過濾條件
dwc_czrw.SetFilter(ls_filter)
dwc_czrw.Filter()
ls_filter = "czx_rwbh = '"+dw_3.GetItemString(dw_3.GetRow(),"czrw_bh")+"'"
dwc_czx.SetSort("czx_sx A")
dwc_czx.Sort()
dwc_czx.SetFilter(ls_filter)
dwc_czx.filter()
當然也可以通過資料共享(ShareData)等方式操作子資料視窗中的資料。
訪問複合資料視窗物件.方法:dw_dy.o b j e c t.dw_1.o b j e c t.物件
例子2 下拉資料視窗動態過濾
在資料視窗dw_1的ItemFocusChanged事件中寫入如下指令碼:
Integer rtncode
String ls_nowFld,ls_deptid,ls_sql
DataWindowChild fld_child
rtncode = dw_1.GetChild("Unit_id",fld_child) //獲得Unit_id欄位名下拉資料視窗的控制代碼
If rtncode = -1 Then MessageBox("錯誤!", "不是下拉資料視窗!")
fld_child.SetTransObject(SQLCA) //設定事務物件
ls_sql = Lower(fld_child.GetSQLSelect())// 獲得DDDW的SQL語句
// 去除Sql 語句中的Where條件子句, 如原Sql 語句中須有Where條件子句,此處則需進行較
//複雜的處理,應視具體情況而定。
if Pos(ls_sql, " where ")>0 then ls_sql = Left(ls_sql,Pos(ls_sql, " where "))
//重新設定Sql 語句中的Where條件子句
ls_deptid=dw_1.Object.dept_id[GetRow()] //取得當前dept_id選定值
ls_sql = ls_sql + " Where dept_id = '" +Trim(ls_deptid)+"'"
//重新設定Sql 語句
fld_child.SetSQLSelect(ls_sql)
fld_child.Retrieve()//取得滿足條件的資料
28 從資料視窗中獲取資料
單條:假設我們要讀取dept_id欄位的第一筆資料,可以用下列方式表示∶li_id = dw_1.o b j e c t.dept_id[1]
假設我們要讀取第一行中第二個欄位的資料,可以用下列方式表示∶ls_name = dw_1.o b j e c t.DATA[1,2]
假設我們要讀取dept_id欄位的所有資料,可以用下列方式表示∶li_array = dw_1.o b j e c t.dept_id.CURRENT
假設我們要讀取過濾緩衝區 (filter buffer) 內dept_id欄位的第一筆資料,可以用下列方式表示∶li_id = dw_1.o b j e c t.dept_id.Filter
[1]
假設我們要讀取從第二筆資料的第一個欄位到第三筆資料的二個欄位之間的資料,表示∶lstr_array = dw_1.o b j e c t.DATA[2,1,3,2]
假設我們要讀取整個第二筆的資料,可以用下列方式表示∶lstr_dept = dw_1.o b j e c t.DATA[2]
使用GetItemX ( )函式 x為string number等
lstr_name = dw_1.getitemstring (li_count , "emp_name") li_count為哪一條
多條:string ls_name[ ]
ls_name = dw_ 1.o b j e c t.emp_name.current
資料的讀取 一般格式∶資料視窗控制元件.Retrieve ( ) 返回個數 ,-1為錯誤
增加資料 資料視窗控制元件.InsertRow (行數) 引數為0加到最後
資料的刪除 資料視窗控制元件.Deleterow (行數)
資料的過濾l 資料視窗控制元件.SetFilter (條件字串).
資料視窗控制元件.Filter ( ) 用法∶將主要緩衝區 (Primary Buffer) 內不符合過濾條件的資料移到過濾緩衝區 (Filter Buffer)
內。
例子:string ls_exp ls_exp = "dept_id = 100" dw_1.SetFilter (ls_exp) dw_1.Filter ( )
排序 dw_1.SetSort ("dept_id") dw_1.Sort ( )
將資料從所有的緩衝區 (Buffer) 中清除 dw_1.ReSet ( )
計算資料數目。例如∶dw_1.Rowcount ( ) 類似: .DeletedCount ( ) .ModifiedCount ( ) .FilteredCount ( )
資料視窗的滾動資料視窗控制元件.ScrollToRow (行數)
29 資料視窗屬性改變:
描述資料視窗物件本身顏色,可以表示如下∶long ll_color ll_color = dw_emplist.Describe ("DataWindow.Color")
描述資料視窗物件內標題 dept_id_t 的顏色,可以表示如下∶long ll_color ll_color = dw_emplist.Describe ("dept_id_t.Color")
修改資料視窗物件本身顏色,可以表示如下:dw_emplist.Modify ("DataWindow.Color = 255")
修改資料視窗物件內標題 dept_id 的顏色,可以表示如下∶dw_emplist.Modify ("dept_id_t.Color = 255")
假設當我們希望在程式執行階段才給予下行條件∶薪水超過 50000 時顯示紅色,低於 50000 時顯示黑色。程式的寫法如下∶
ls_modstring = "Salary.Color = '0~tIf (Salary > 50000,255,0) '"
dw_1.modify (ls_modstring)
30 得到當前滑鼠所指物件所在的帶區
string str_band
str_band=GetBandAtPointer() //得到當前滑鼠所指物件所在的帶區
str_band=left(str_band,(pos(str_band,'~t') - 1))//得到"header"、"detail"等
if str_band<>'header' then return //單擊非頭區,退出
31 得到滑鼠指向的列物件名
str_o b j e c t=GetObjectAtPointer() //得到當前滑鼠所指物件名
str_o b j e c t=left(str_o b j e c t,(pos(str_o b j e c t,'~t') - 1))
//得到列物件名(預設為列名_t為列標題)
str_column=left(str_o b j e c t,(len(str_title) - 2))
//判斷該名稱是否為列名字
if this.describe(str_column+".band")='!' then return //非是列名,即列標題不是按正常規律起名的。
32 得到當前行、列,總行、列 //this 針對資料視窗而言
li_col = this.GetColumn()
li_ColCount = long(describe(this,"datawindow.column.count"))
ll_row = this.GetRow()
ll_RowCount = this.RowCount()
//設定當前行、列
scrolltorow(this,ll_Row)
setrow(this,ll_Row)
setcolumn(this,li_col)
this.SetFocus()
33 得到所有列標題
ll_colnum = Long(dw_1.o b j e c t.datawindow.column.count)
for i = 1 to ll_colnum
//得到標題頭的名字
ls_colname = dw_1.describe('#' + string(i) + ".name") + "_t"
ls_value = dw_1.describe(ls_colname + ".text")
next
34 如何用程式碼取得資料視窗彙總帶計算列的值?
String ls_value
ls_value = dw_1.Describe("Evaluate("'compute_1',1)")
如果是數值型,要轉換。
35 取得單擊的列標題、列名、資料庫欄位名
string ls_dwo
long ll_pos
string ls_type
string ls_title
string ls_column
string ls_dbname
if Not KeyDown(KeyControl!) then return
ls_dwo = dwo.Name
if trim(ls_dwo) = '' or isnull(ls_dwo) then return
ls_type = This.describe(ls_dwo + '.type')
if ls_type = 'column' then
ls_title = This.describe(ls_dwo + '_t.text')//標題
ls_column = This.describe(ls_dwo + '.Name') //資料視窗列名
ls_dbname = This.describe(ls_dwo + '.dbname') //資料庫中欄位名
messagebox('資訊', '標 題 文 本 :' + ls_title + &
'~r~n資料視窗列名 :' + ls_column + &
'~r~n資料庫中欄位名:' + ls_dbname )
end if
36 視窗為w_gcde內,放入一個DW_1,如何得到dw_1內的某列值yuonghu_id列的內容
方法:
long lng_column_count
integer i
string str_column[] //列名
string str_column_text[] //text的名字
//得到資料視窗的總列數
lng_column_count = long(dw_1.Describe("DataWindow.Column.Count"))
//迴圈依次讀取
for i = 1 to lng_column_count
str_column[i] = dw_1.Describe("#"+string(i)+".name")
str_column_text[i] = dw_1.Describe(str_column[i] + "_t.text")
next
37 在DDDW中實現當前高亮行隨滑鼠移動
DataWindowChild ldwc_Child
String ls_Pointer
Long ll_Row
GetChild( "dept_id", ldwc_Child ) // Replace the column name "dept_id" as you needed
IF hwndchild = Handle( ldwc_child ) THEN
if notificationcode = 2311 then //DDDW的mousemove事件
//得到滑鼠所在行
ls_Pointer = ldwc_Child.GetObjectAtPointer()
ll_Row=Long( Mid( ls_Pointer, Pos( ls_Pointer, "~t" ) + 1 ))
//移到滑鼠所在行
IF ldwc_Child.GetRow() <> ll_Row AND ll_Row > 0 THEN
ldwc_Child.ScrollToRow( ll_Row )
END IF
end if
END IF
38 實現列印完一個DataWindow後不換頁
首先將datawindow的print輸出到一個列印檔案中,把其他的print也輸入這個prn,然後,列印這個列印檔案就行了。
如:
datawindow_control1.object.datawindow.print.filename="c:printfilepathexam_1.prn"
datawindow_control2.object.datawindow.print.filename="c:printfilepathexam_1.prn"
dw_1.print()
dw_2.print()
run("print //d:/printservenamesharename "c:printfilepathexam_1.prn")
//d:/printservenamesharename印表機名