當前位置:工程項目OA系統(tǒng) > 泛普各地 > 河北O(jiān)A系統(tǒng) > 石家莊OA系統(tǒng) > 石家莊OA信息化
XML Web Service-Enabled Office Documents
XML Web Service-Enabled Office Documents
Chris Lovett
Microsoft Corporation
March 19, 2001
Download or browse the xml03192001.exe in the MSDN Online Code Center.
Are you ready for a marriage of Microsoft Office XP and .NET Web Services? In a networked world of B2B e-commerce, why not deliver the power of Web Services to the end user by integrating business process workflow right into everything people do from their desktop? What am I talking about? Well, an Excel spreadsheet that looks something like Figure 1.
Figure 1. Web Services-enabled Excel spreadsheet
This is not just an ordinary spreadsheet. It uses UDDI to find company addresses and it uses a Catalog Web Service to find product information. It also does an XML transform on the XML spreadsheet format to generate a RosettaNet PIP 3 A4 Purchase Order Request format when you click the Send button.
When you type in the name of the company you are purchasing from, and then click on the Find button, some VBA code behind the spreadsheet makes a UDDI call and fills out the rest of the address section. For example, type in Microsoft, click Find, and you should see the following in the Purchase From fields:
Figure 2. Purchase From field
When you type in a quantity of, say, 23, and then the term Pear in the description field, then press the TAB key, some VBA code queries a SOAP Catalog Web Service to see if it can find a matching product, then it fills out the details. In this case, I have wired the Catalog Web Service to the Northwind database, so it returns the following:
Figure 3. Detailed look at the order portion of the spreadsheet
In this case, it has also filled out the description and turned it into a link which takes you to an HTML page that tells you all about that product.
If more than one product is found and none of them matches exactly to what you typed, then a drop down list of choices is provided. For example, if you type tofu, you'll see the following choices:
Figure 4. Example of multiple choices provided when an exact match is not found
When you select one of these choices, then the specific details are provided.
When you're done, you click the Send button and the RosettaNet PIP 3 A4 XML Purchase Order format is generated, and the order is sent.
How Does All This Work?
You can browse
the VBA code behind the spreadsheet by going to the Tools menu, select Macro,
then Visual Basic Editor. There's a bit of code behind ThisWorkbook that reacts
to changes in the spreadsheet, in particular the Workbook_SheetChange event
clears out a line item when you delete the description and the
Workbook_SheetSelectionChange event calls FindProduct() when you tab out of the
Description field into the SKU field. If FindProduct returns an XMLNode, then
the relevant fields are pulled out of that node to populate the rest of the line
item details.
How the UDDI find_business call works can be found in my earlier article UDDI: An XML Web Service. If a business is found, the addressLines found in the /businessInfo/contacts/contact/address/ part of the UDDI response are used to populate the Purchase From address block.
Catalog Web Service
The FindProduct
function in the Catalogs module calls the Catalog Service URL with a URL
parameter containing the search term to lookup. It expects to get a SOAP
response back and first checks to see if it matches /Envelope/Body/Fault, if it
is not a Fault, it proceeds to crack open the <CatalogQueryResult>
checking to see if the ProductName attribute in any returned items match the
given term. It also builds the drop-down list of choices further down the page
outside of the visible area. You can see how the drop-down list works by going
to the Data menu and selecting Validation.
The Catalog Web Service is very simple. The .aspx entry point simply creates a CatalogSearch object which is defined in search.cs and calls Execute, passing the HttpResponse output stream as follows:
<%@Language="C#" src="search.cs"
Debug="true" %>
<%
Response.ContentType =
"text/xml";
string term =
Request.QueryString["term"];
if (term != null)
{
CatalogSearch s = new
CatalogSearch(term);
s.Execute(output);
} else
{
Response.Write("<Empty/>");
}
%>
The Execute method is where the fun begins. This is very simple SQL Managed Provider code wrapped in an XmlTextWriter that returns the specific fields from the SQL SELECT statement. So it is basically a while loop through the DataReader, writing to the XmlTextWriter as follows:
public void Execute(TextWriter
stm)
{
XmlTextWriter
xw = new XmlTextWriter(stm);
xw.WriteStartElement("Envelope", "http://schemas..../envelope/");
xw.WriteStartElement("Body", "http://schemas..../envelope/");
try {
String const =
"server=localhost;uid=sa;pwd=;database=northwind";
SQLConnection con = new
SQLConnection(constr);
con.Open();
IDataReader
reader;
String query = "SELECT
ProductName,UnitPrice,QuantityPerUnit,"
+
"SupplierID,ProductID FROM Products WHERE "
+
"ProductName LIKE '%" + term + "%'";
SQLCommand cmd = new SQLCommand(query,
con);
cmd.Execute(out
reader);
string funNamespace =
"urn:schemas-b2b-fun:catalogs";
xw.WriteStartElement("CatalogQueryResult",
funNamespace);
while
(reader.Read())
{
xw.WriteStartElement("item");
xw.WriteAttribute("ProductName",
reader.GetString(0));
xw.WriteAttrDecimal("UnitPrice",
reader.GetDecimal(1));
xw.WriteAttribute("UnitOfMeasure",
reader.GetString(2));
xw.WriteAttribute("SKU",
"S"+reader.GetInt32(3)+
"-P"+reader.GetInt32(4));
xw.WriteEndElement();
}
xw.WriteEndElement();
con.Close();
} catch
(Exception e) {
xw.WriteStartElement("Fault");
xw.WriteElementString("faultcode","500");
xw.WriteElementString("faultstring",e.ToString());
xw.WriteEndElement();
}
xw.WriteEndElement();
xw.WriteEndElement();
xw.Close();
}
The URL http://localhost/catalog/search.aspx?term=tofu returns the following result:
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<CatalogQueryResult
xmlns="urn:schemas-b2b-fun:catalogs">
<item
ProductName="Tofu" UnitPrice="23.25"
UnitOfMeasure="40 - 100 g
pkgs." SKU="S6-P14"/>
<item
ProductName="Longlife Tofu" UnitPrice="10"
UnitOfMeasure="5 kg
pkg." SKU="S4-P74"/>
</CatalogQueryResult>
</Body>
</Envelope>
This is about the most efficient way you can get XML out of SQL Server using the .NET frameworks. With a very rough measurement, I got about 80 to 90 of these per second on my Dell PowerEdge 2400.
Send Button
The SendOrder() function
loads an XML document from an XML representation of a selected range of cells in
the spreadsheet. This is done with the following magic lines of VBA
code:
With ActiveSheet
Set sourcexml = New
MSXML2.DOMDocument
sourcexml.loadXML
.Range("B1:N34").value(xlRangeValueXMLSpreadsheet)
End With
This returns a huge chunk of XML that fully describes everything about that range of cells in the spreadsheet. The following is a snippet from the chunk of XML:
<Workbook>
<Worksheet>
<Table>
<Row>
<Cell ss:StyleID="s23"><Data
ss:Type="Number">23</Data>
<NamedCell
ss:Name="Item"/></Cell>
<Cell ss:MergeAcross="4"
ss:StyleID="m31209522"
ss:HRef="http://eshop.msn.com/category.asp?catId=170">
<Data ss:Type="String">Uncle Bob's Organic Dried
Pears</Data></Cell>
<Cell
ss:StyleID="s52">
<Data
ss:Type="String">S3-P7</Data></Cell>
<Cell ss:StyleID="s26">
<Data
ss:Type="Number">30</Data>
<NamedCell
ss:Name="UnitPrice"/></Cell>
<Cell ss:StyleID="s27">
<Data ss:Type="String">12 - 1 lb
pkgs.</Data></Cell>
<Cell
ss:StyleID="s37">
<Data
ss:Type="Number">690</Data></Cell>
<Cell
ss:StyleID="s49"/>
</Row>
</Table>
</Worksheet>
</Workbook>
Then we use XSL to turn this into the following format:
<PurchaseOrder xmlns="http://www.rosettanet.org">
<deliverTo>
<PhysicalAddress>
<cityName>Seattle, WA, USA
98111</cityName>
<addressLine1>Airport
Chocolates</addressLine1>
<addressLine2>2711 Alaskan
Way</addressLine2>
<regionName>USA</regionName>
</PhysicalAddress>
</deliverTo>
<ProductLineItem>
<ProductQuantity>23</ProductQuantity>
<productUnit>
<ProductPackageDescription>
<ProductIdentification>
<GlobalProductIdentifier>S3-P7</GlobalProductIdentifier>
</ProductIdentification>
</ProductPackageDescription>
</productUnit>
<Description>Uncle Bob's Organic Dried
Pears</Description>
<requestedPrice>
<FinancialAmount>
<GlobalCurrencyCode>USD</GlobalCurrencyCode>
<MonetaryAmount>30</MonetaryAmount>
</FinancialAmount>
</requestedPrice>
</ProductLineItem>
<thisDocumentGenerationDateTime>
<DateTimeStamp>2001-03-15T00:00:00.000</DateTimeStamp>
</thisDocumentGenerationDateTime>
</PurchaseOrder>
Note This is probably not a technically complete
Request according to RosettaNet PIP 3 A4 Purchase Order Request specification,
but you get the idea.
The trick to making this transformation somewhat robust
is to name the important cells that we want to pull the data out of. This is
done with the following style of XPath expression in the XSLT
transform:
select="/Workbook/Worksheet/Table/Row/Cell[NamedCell[@ss:Name='City']]
This particular expression finds the Cell that is Named with the name City. The rest of the stylesheet is pretty straight forward. See XLToPO.xsl for additional information.
Try It Out
To get this running, all you
need to do is install MSXML 3.0 and get a hold of a Northwind database. The demo
code is wired to SQL Server as follows:
SQLConnection("server=localhost;uid=sa;pwd=;database=northwind");
You may need to change this bit of code if your Northwind database is elsewhere.
The PO.xsl spreadsheet is expecting the Catalog Service to be located at:
http://localhost/catalog/search.aspx
You will need to install the Web Service search.aspx, search.cs, and XLToPO.xsl in a virtual directory called catalog on your local machine, or change the spreadsheet to point elsewhere.
To edit the spreadsheet you will have to turn off protection, which can be done using the Tools/Protection submenu.
Next Steps
Ideally, you would want to
store the supplier's Catalog Service bindings in UDDI. There is some VBA code
commented out that will do this for you. It looks for a recognized Catalog
Service serviceInfo (by serviceKey) and if it finds it, it then uses the
accessPoint contained within the serviceDetails. The pseudo-catalog API I'm
using in this demo is not registered as a known service type in UDDI.
It would be a fun exercise to make use of Office Smart Tags to do similar things. See the Smart Tags SDK on http://msdn.microsoft.com/office/ for some additional information.
- 1協(xié)同辦公OA軟件的常用資料和規(guī)章制度
- 2Web服務內幕,第10部分:深入主題:可靠性和事務
- 3Accessing Web Services From DHTML
- 4BEA舉辦BEA WebLogic Platform 7.0新產(chǎn)品推介會
- 5關于群體智慧積累和傳遞的思考(by AMT 王玉榮)
- 6MSDN Online Voices - Extreme XML:已啟用XML Web服務的Office文檔
- 7知識地圖在項目型組織中的應用
- 8《變革之舞-學習型組織持續(xù)發(fā)展面臨的挑戰(zhàn)》
- 9Favorites Service Overview
- 10出版社行業(yè)如何做好信息化建設的思考
- 11At Your Service, On the Web
- 12微軟、IBM和BEA聯(lián)合發(fā)表Web服務新標準
- 13石家莊OA信息化,知識組織和知識工作者:來自前沿的觀點
- 14美國三大IT巨頭將向OASIS提交Web服務安全標準
- 15InterOP Stack新一代平臺互操作技術:InterOP Stack技術應用前瞻
- 16ITToolBox e-Business(by AMT整理)
- 17架構Web Service:基于Web服務的應用、解決方案和開發(fā)平臺
- 18網(wǎng)絡、知識增長和經(jīng)濟發(fā)展
- 19構建石家莊OA信息化系統(tǒng)的探討
- 20從紡織行業(yè)看知識庫及專家系統(tǒng)構建信息平臺
- 21中國特色生態(tài)文明建設的理論創(chuàng)新和實踐
- 22Consuming a Web Service from a Win Form Application
- 23Web Services 及其技術(上)
- 24[原創(chuàng)]淺談KM的知識源采集和技術實現(xiàn)
- 25石家莊泛普OA軟件管理門戶登錄
- 26Web Service初探
- 27鼓勵創(chuàng)新的文化的十個規(guī)則
- 28協(xié)同辦公OA軟件對系統(tǒng)登陸的安全設置
- 29Web服務 按需服務——Sun ONE為企業(yè)建立服務驅動型網(wǎng)絡
- 30企業(yè)借OA節(jié)省費用,減輕金融風暴影響
成都公司:成都市成華區(qū)建設南路160號1層9號
重慶公司:重慶市江北區(qū)紅旗河溝華創(chuàng)商務大廈18樓