|
大多數(shù)公司由于意識(shí)到無文檔的工作過程會(huì)成為前進(jìn)的絆腳石,因此都開發(fā)了定義詳細(xì)的文檔程序。每個(gè)公司都為不同的過程定義自己的一套文檔模板,使它們隨時(shí)可被職員使用,用于進(jìn)行購(gòu)買請(qǐng)求或申請(qǐng)度假等。 但是,隨著Internet 逐漸為大家熟悉和逐漸普及,越來越多的功能被移植到“開放空間”,以實(shí)現(xiàn)更好的可視性和更有效的通訊。比如說,一個(gè)人也許要問:“我可以登錄到Internet / Intranet,填寫一張休假申請(qǐng)表,然后以公司標(biāo)準(zhǔn)模板樣式將它作為Word 文檔發(fā)送給我的經(jīng)理嗎?”答案是肯定的,下面會(huì)為你演示如何實(shí)現(xiàn)。
關(guān)于這個(gè)應(yīng)用程序 我們的應(yīng)用程序有一個(gè)樣本表格,由訪問web 站點(diǎn)的用戶填寫。一旦提交,ASP文件收集其中信息,使用web 服務(wù)器上存放的預(yù)先定義的模板,以其內(nèi)容創(chuàng)建一個(gè)Word 文檔。然后顯示一個(gè)鏈接,允許用戶查看或者下載這個(gè)文檔。
我們創(chuàng)建一個(gè)Visual Basic COM 組件(ActiveX DLL), 通過ASP應(yīng)用程序調(diào)用它,給它傳遞必要的參數(shù)。組件從本質(zhì)上是使用Microsoft Word 對(duì)象庫(kù),創(chuàng)建一個(gè)對(duì)將要傳遞參數(shù)的 Word 文檔的引用。所有這些都是在服務(wù)器上完成的,因?yàn)檫@種方法有許多優(yōu)勢(shì)。
其中最重要的是在程序內(nèi)運(yùn)行的since.dll (與網(wǎng)絡(luò)服務(wù)器在同樣的內(nèi)存中),它們比程序外運(yùn)行的(如CGI或Perl 腳本)運(yùn)行更快,使用的資源更少,后者在運(yùn)行中每次被調(diào)用時(shí),都將創(chuàng)建自己本身的實(shí)例(如復(fù)制)作為單獨(dú)的程序,因此要用掉大量的服務(wù)器內(nèi)存。這還意味著為了使程序外組件在服務(wù)器上運(yùn)行(關(guān)鍵字:ASPAllowOutOfProcComponents),你不需要修改Metabase (一個(gè)存儲(chǔ)Internet信息服務(wù)器配置設(shè)置的結(jié)構(gòu),與Windows 注冊(cè)相同,但是使用較少的磁盤空間)。
另一方面,這種方法最明顯的缺點(diǎn)也許是因?yàn)樗c網(wǎng)絡(luò)服務(wù)器在同樣的內(nèi)存空間中運(yùn)行,任何DLL的問題都有可能使服務(wù)器出故障。因此,在開發(fā)和執(zhí)行程序內(nèi)應(yīng)用程序時(shí)需要十分小心。
程序要求和優(yōu)點(diǎn)
完成本文所說的功能,需要具備以下條件: ● Visual Basic 5 或 6 ● 具備IIS 4的NT服務(wù)器 或 工作站,或者有PWS 的任何 Windows 9.x ● MS Word 97 ( Office 97 套裝的一部分)
本例還可以和MS Word 2000一起執(zhí)行,但是會(huì)有一些問題,在文章最后要提到。其它額外的軟件是不必要的,只需要保證默認(rèn)站點(diǎn)http://localhost/ 是有效的(點(diǎn)擊這個(gè)超鏈接會(huì)把你帶到個(gè)人的web 服務(wù)器或Windows NT 的主頁)。 我們將把創(chuàng)建的所有文檔都存儲(chǔ)在C:\Inetpub\scripts\documents 文件夾中, 所以一旦文檔被創(chuàng)建之后,我們提供到它的鏈接是很容易的(可以根據(jù)需要修改)。一定要?jiǎng)?chuàng)建這個(gè)路徑,否則我們的例子就不能工作。所有其它的文件都位于我們的腳本路徑 ( C:\Inetpub\scripts )。我們的dll 將盡可能地靈活,使任何模板的修改都只需要最少的代碼修改。
更深一層的技術(shù)
要設(shè)計(jì)的模板可以基于一個(gè)公司希望在他們的文檔出現(xiàn)的內(nèi)容:登錄、適當(dāng)?shù)捻撁己晚撃_信息、基本文本等等。另外文檔創(chuàng)建之后,我們希望在其中看到用戶特殊信息的地方還要加入標(biāo)記(這就使這個(gè)應(yīng)用程序是動(dòng)態(tài)的)。在我們回顧代碼時(shí)還會(huì)仔細(xì)看這些部分。我們的.dll 將包含一個(gè)稱為GenerateDocument 的函數(shù)(在類文件內(nèi)部),它要求向它傳遞4個(gè)參數(shù),分別是: ● 一個(gè)為所有標(biāo)記用的分界字符串(來自文本模板) ● 一個(gè)為所有相應(yīng)值用的分界字符串(來自 web瀏覽器上用戶填充的表格) ● 模板在服務(wù)器上的位置 ● 生成的文檔在服務(wù)器上被存儲(chǔ)的位置
現(xiàn)在我們可以往下進(jìn)行了。
組合在一起 文檔模板 首先創(chuàng)建一個(gè)word 模板的樣本,假設(shè)它就是我們公司的標(biāo)準(zhǔn)文檔模板。我們要為這個(gè)例子獲取職員的信息,我們希望文檔中包含以下的特定信息:名字、地址、Email Id,F(xiàn)在基于這些信息創(chuàng)建模板,一定要在文檔中將要顯示用戶信息的地方包含適當(dāng)?shù)臉?biāo)記(如. < Name >, < Address >)。
將文件命名為EmployeeTemplate.dot(記住,在Save As 對(duì)話框的文件類型列表中選擇文檔模板,并將其存入C:\Inetpub\Scripts\Templates\。看看可下載材料部分包含的文檔模板樣本,以便對(duì)它有個(gè)更好的理解。
COM組件 現(xiàn)在用Visual Basic創(chuàng)建COM組件,按照以下的步驟: ● 啟動(dòng) Visual Basic, 選擇 ActiveX DLL 作為工程文件類型。 ● 將類名改為DocumentObject, 工程文件名改為 MyDocumen(這是我們?cè)贏SP頁中創(chuàng)建COM組件的一個(gè)例示時(shí)要使用的信息) ● 接著,點(diǎn)擊工程文件菜單選項(xiàng),到 References。 ● 向下滾動(dòng)直到看見 "Microsoft Word n.0 Object Library " (n 是一個(gè)識(shí)別服務(wù)器上安裝的word對(duì)象庫(kù)版本的數(shù)字).選中這個(gè)選項(xiàng),點(diǎn)擊click OK。
請(qǐng)參閱本文結(jié)尾處可下載文件中的類模塊代碼。GenerateDocument()函數(shù)要用到從ASP文件向它傳遞的4個(gè)參數(shù)。 它返回一個(gè)字符串類型,在后面可以看到: Option Explicit ' Declare a New word application Object Dim wdApp As New Word.Application Public Function GenerateDocument(sTags, sValues, sSourcePath, sDestPath) _ As String On Error GoTo ErrHandler Dim arrTags() As String, arrValues() As String, iLoop As Integer
此函數(shù)執(zhí)行的第一個(gè)任務(wù)是從指定的源路徑(作為參數(shù)從ASP文件傳遞過來)打開模板文件;谠诜⻊(wù)器上創(chuàng)建的模板,引用一個(gè)新的Word 文檔: wdApp.Documents.Open sSourcePath
然后,將從HTML表單中獲取的所有標(biāo)記,用Split 函數(shù)放入arrTags數(shù)列中。逗號(hào)是一個(gè)分界符,在ASP文件中分隔開標(biāo)記的值: arrTags = Split(sTags, ", ")
我們將相應(yīng)的用戶輸入值存入arrValues數(shù)列。pipe 字符( | ) 是分界符,來分隔開這些值:arrValues = Split(sValues, " | ") 代碼在arrTags 中循環(huán) ,用查找和代替操作(用應(yīng)用程序腳本的Visual Basic)從標(biāo)記數(shù)列中找到標(biāo)記,在創(chuàng)建的Word文檔中,用arrValues 數(shù)列中的相應(yīng)值代替它們:
For iLoop = 0 To UBound(arrTags) wdApp.ActiveDocument.Content.Find.Execute arrTags(iLoop), , True, , _ , , , , , arrValues(iLoop), 2 Next iLoop
你看到的一串逗號(hào)是Find-Execute 方法的不同屬性,我們沒有設(shè)置。我們只對(duì) MatchWholeWord, ReplaceWith和ReplaceAll(用數(shù)字常量2代表)的設(shè)置選擇感興趣。然后,我們將文檔存入指定的目的路徑和文件名中,退出和釋放之前關(guān)閉這個(gè)word文檔對(duì)象:
wdApp.ActiveDocument.SaveAs sDestPath wdApp.ActiveDocument.Close wdApp.Quit Set wdApp = Nothing 退出函數(shù)之前,返回一個(gè)'Success' 標(biāo)志: GenerateDocument = "Success" Exit Function 這是一個(gè)錯(cuò)誤處理程序。如果在上面的應(yīng)用程序執(zhí)行中遇到錯(cuò)誤的話,它返回一個(gè)錯(cuò)誤信息。 ErrHandler: ' Quit and release the word document object wdApp.Quit Set wdApp = Nothing ' Build the Error Message, and pass it back Dim ErrMsg As String ErrMsg = "Error Number: " & Err.Number & "< BR >< BR >" ErrMsg = ErrMsg & "Error Source: " & Err.Source & "< BR >< BR >" ErrMsg = ErrMsg & "Error Description: " & Err.Description & "< BR >< BR >" GenerateDocument = ErrMsg Exit Function End Function Private Sub Class_Terminate() ' Release the reference Set wdApp = Nothing End Sub
在Visual Basic中,保存應(yīng)用程序(保留類和工程文件名),編譯,看是否產(chǎn)生了什么錯(cuò)誤。然后,打開File 菜單, 點(diǎn)擊Make MyDocument.dll。保留它的名字,在工程文件所在的文件夾中保存它。
然后,在web 服務(wù)器上注冊(cè)dll,如下: ● 將 MyDocument.dll 復(fù)制到windows\system 或 winnt\system32路徑(取決于使用的操作系統(tǒng)). ● 在命令提示符下執(zhí)行以下命令 C:\winnt\system32 >regsvr32 MyDocument.dll ● 你將看到一個(gè)成功的信息:DllRegisterServer in MyDocument.dll 。 上面完成了這個(gè)應(yīng)用程序的主要部分,F(xiàn)在進(jìn)入下一步。
HTML 頁面
現(xiàn)在需要?jiǎng)?chuàng)建HTML頁面( EmployeeForm.html ),用戶將在其中輸入填充到新Word 文檔中的值。下面是我們使用的HTML頁樣本: < HTML > < TITLE > Employee Registration Page < /TITLE > < BODY BGCOLOR=#ECECEC > < CENTER >< FONT FACE=arial SIZE=-1 > < FONT SIZE=5 > Employee Registration Page < /FONT > < HR ALIGN=center COLOR=black >< BR > Please complete your details as per the Registration Form...< BR >< BR > < TABLE CELLSPACING=1 CELLPADDING=5 BGCOLOR="#000000" BORDER=0 ALIGN=center > < FORM ACTION=CustomDoc.asp METHOD=post > < TR > < TD BGCOLOR=#00BCA8 COLSPAN=2 ALIGN=center > < B > < FONT FACE=arial SIZE=-1 COLOR=black > Employee Details < /TD > < /TR > < TR > < TD BGCOLOR=#C4C2C2 > < B >< FONT FACE=arial SIZE=-1 COLOR=black >Your Name: < /TD > < TD BGCOLOR=#E3E1E1 > < INPUT TYPE=Text NAME="Name" SIZE=20 MAXLENGTH=25 > < /TD > < /TR > < TR > < TD BGCOLOR=#C4C2C2 > < B >< FONT FACE=arial SIZE=-1 COLOR=black >Address: < /TD > < TD BGCOLOR=#E3E1E1 > < INPUT TYPE=Text NAME="Address" SIZE=40 MAXLENGTH=40 > < /TD > < /TR > < TR > < TD BGCOLOR=#C4C2C2 > < B >< FONT FACE=arial SIZE=-1 COLOR=black >City, State: < /TD > < TD BGCOLOR=#E3E1E1 > < INPUT TYPE=Text NAME="City" SIZE=20 MAXLENGTH=20> < INPUT TYPE=Text NAME="State" SIZE=20 MAXLENGTH=20 > < /TD > < /TR > < TR > < TD BGCOLOR=#C4C2C2 > < B >< FONT FACE=arial SIZE=-1 COLOR=black >Zip, Country: < /TD > < TD BGCOLOR=#E3E1E1 > < INPUT TYPE=Text NAME="Zip" SIZE=20 MAXLENGTH=20 > < INPUT TYPE=Text NAME="Country" SIZE=20 MAXLENGTH=20 > < /TD > < /TR > < TR > < TD BGCOLOR=#C4C2C2 > < B >< FONT FACE=arial SIZE=-1 COLOR=black >Email: < /TD > < TD BGCOLOR=#E3E1E1 > < INPUT TYPE=Text NAME="Email" SIZE=40 MAXLENGTH=40> < /TD > < /TR > < TR > < TD BGCOLOR=#00BCA8 COLSPAN=2 > < INPUT TYPE=Submit VALUE="Save and Generate Profile Document" > < INPUT TYPE=Reset VALUE="Clear Fields" > < /TD > < /TR > < /FORM > < /TABLE > < /BODY >< /HTML > 將文件存入C:\Inetpub\scripts\ 中,要確定腳本路徑在個(gè)人Web服務(wù)器或IIS中有讀取并執(zhí)行權(quán)限。
ASP頁面 ASP頁( CustomDoc.asp ) 實(shí)際完成以下任務(wù):取得用戶輸入、用COM組件創(chuàng)建Word 文檔、 將它遞交回用戶。下面是帶注釋的代碼: < % Dim sTags, sValues, sDestPath, sSourcePath, resValue ' Get all the User Input values from the Form sName = Request("Name") sAddress = Request("Address") sCity = Request("City") sState = Request("State") sZip = Request("Zip") sCountry = Request("Country") sEmail = Request("Email") sDate = Now() ' Create a list of all the tags as defined in the Word Template by You sTags = "< Name >, < Address >, < City >, < State >, < Zip >, < Country >, " & _ "< Email >, < Date >" ' Gather up all the User Input values into one delimited string sValues = sName & " | " & sAddress & " | " & sCity & " | " & sState & _ " | " & sZip & " | " & sCountry & " | " & sEmail & " | " & sDate
完成之后,需要識(shí)別源文件(Template) 和目標(biāo)文件(Document)的位置。APPL_PHYSICAL_PATH 返回CustomDoc.asp 文件所在的路徑。我們將文檔文件夾和文件名附加在一起,這是用戶負(fù)空間的名字。
sSourcePath = Request.ServerVariables("APPL_PHYSICAL_PATH") & _ "Templates\" & "EmployeeTemplate.dot" sDestPath = Request.ServerVariables("APPL_PHYSICAL_PATH") & _ "Documents\" & Replace(sName, " ","") & ".doc"
現(xiàn)在完成了常見MyDocument對(duì)象的例示和調(diào)用GenerateDocument.doc,在返回值的基礎(chǔ)上進(jìn)行適當(dāng)?shù)牟僮鳌?br>Set myDocObj = Server.CreateObject("MyDocument.DocumentObject") ' Call the GenerateDocument function while passing the required ' Parameters retValue = myDocObj.GenerateDocument(sTags, sValues, sSourcePath, _ sDestPath) ' Take appropriate action based on the returned value If retValue = "Success" Then Msg = "Successfully generated your Document : " & Replace(sName, _ " ", "") & ".doc" Response.Write("< font face=arial size=-1 color=Green >< br >" & Msg) Response.Write("< br >< br >< a href=Documents/" & _ Replace(sName, " ","") & ".doc" & " >Here it is!< /a >") Else Response.Write("< font face=arial size=-1 color=Red >< br >" & retValue) End If % > 將文件存入C:\Inetpub\scripts\。就行了,F(xiàn)在在瀏覽器中鍵入 http://localhost/scripts/EmployeeForm.html,執(zhí)行應(yīng)用程序,輸入所有的域值,點(diǎn)擊 Save and Generate Profile Document,F(xiàn)在可以看到我們的方法是多么有效和美觀了。
對(duì)于Office 2000 的問題
如果你的機(jī)器安裝了Word 2000,并且用Microsoft word 9.0 對(duì)象庫(kù)創(chuàng)建dll 的話,就會(huì)遇到一些問題。組件本身好象工作得絕對(duì)良好,沒有任何錯(cuò)誤,但是從ASP頁調(diào)用會(huì)操作超時(shí),或產(chǎn)生一個(gè)ActiveX 不能創(chuàng)建對(duì)象的錯(cuò)誤。這也許是Office 2k設(shè)計(jì)上的特色,或者也許是一個(gè)錯(cuò)誤(Bug)。下面解釋一下為什么會(huì)發(fā)生這些問題。大致來說,這是因?yàn)榘踩庞貌荒茉谒械睦咀訉?duì)象中持續(xù)。當(dāng)調(diào)用一個(gè).asp 頁時(shí)它作為IUSR 帳號(hào)(web 服務(wù)器上的默認(rèn)internet 客戶帳號(hào))持續(xù)。當(dāng)調(diào)用我們創(chuàng)建的COM組件時(shí),IUSR 信用也被傳遞。
這個(gè)COM反過來產(chǎn)生對(duì)office COM (子對(duì)象)的調(diào)用,但是卻不能傳遞信用。為了克服這個(gè)問題,我們需要這樣做: ● 打開組件服務(wù)控制臺(tái), 然后在COM+ Applications點(diǎn)擊右鍵。 ● 選擇 New Application,跟隨 COM 應(yīng)用程序向?qū)? 命名一個(gè)空的app。
● 打開新的應(yīng)用程序,在 Components上點(diǎn)擊右鍵。 ● 選擇創(chuàng)建一個(gè)新組件,選擇置入已經(jīng)注冊(cè)的組件。 ● 在下一個(gè)對(duì)話框的組件列表中,選擇MyDocument.DocumentObject,點(diǎn)擊finish。應(yīng)用程序現(xiàn)在就 很可能工作了。 通過將COM 投入MTS ,我們?cè)试SCOM持續(xù)為特定帳號(hào),將它傳遞給調(diào)用的COM(在這個(gè)操作以前好象沒有發(fā)生過)。我猜想這是因?yàn)镸icrosoft只允許一級(jí)安全信用持續(xù), 我懷疑不需要這樣做也可以把信用持續(xù)下去。
觀察和結(jié)論 我們已經(jīng)基本上完成了。開發(fā)應(yīng)用程序時(shí)還有一些需要注意。 ● 如果你仔細(xì)觀察組件的設(shè)計(jì),你會(huì)觀察到即使你已經(jīng)從模板修改、增加、刪除了標(biāo)記或文本,也根本不需要修改代碼。它是可以再利用的。只需要通過ASP文件傳遞一些參數(shù),你就可以快速創(chuàng)建符合公司口味的Word 文檔了。 ● 你可以根據(jù)需要定制它。只需要保證在模板文件中,你的標(biāo)記是唯一的(在兩個(gè)不同的上下文中不要 使用相同的標(biāo)記)。 ● 還可以加強(qiáng)應(yīng)用程序的功能,一旦創(chuàng)建,就可以根據(jù)輸入的Email ID (或從數(shù)據(jù)庫(kù)中)直接將文檔email給用戶,以實(shí)現(xiàn)交互式的改進(jìn)。 ● 在ASP文件中的標(biāo)記和值字符串,應(yīng)該彼此同步,盡管在模板文件中它們不一定會(huì)同步出現(xiàn)。
|