在網(wǎng)絡(luò)瀏覽器軟件中,可以Internet Explorer (IE)現(xiàn)在是一種標(biāo)準(zhǔn)的軟件。可以看到,運(yùn)行不同版本的Windows操作系統(tǒng)(和很多其他的操作系統(tǒng))的每一臺(tái)機(jī)器幾乎都使用IE。微軟已經(jīng)通過ActiveX控件將IE的功能包含在執(zhí)行成熟的XML處理技術(shù)中。
在本篇文章中,我們將講述如何在IE中使用ActiveX功能來訪問并解析XML文檔,由此允許網(wǎng)絡(luò)沖浪者操縱它們。
網(wǎng)上沖浪
我們以一個(gè)標(biāo)準(zhǔn)的順序文檔而開始,如表A所示。這一文檔包含簡(jiǎn)單的順序數(shù)據(jù)以提供網(wǎng)絡(luò)沖浪者瀏覽之用。不僅僅為了顯示這些數(shù)據(jù),我們還提供了一個(gè)簡(jiǎn)單的用戶界面,網(wǎng)上沖浪都可以使用這一界面來瀏覽XML文檔。
表A: order.xml
<?xml version="1.0" ?>
<Order>
<Account>9900234</Account>
<Item id="1">
<SKU>1234</SKU>
<PricePer>5.95</PricePer>
<Quantity>100</Quantity>
<Subtotal>595.00</Subtotal>
<Description>Super Widget Clamp</Description>
</Item>
<Item id="2">
<SKU>6234</SKU>
<PricePer>22.00</PricePer>
<Quantity>10</Quantity>
<Subtotal>220.00</Subtotal>
<Description>Mighty Foobar Flange</Description>
</Item>
<Item id="3">
<SKU>9982</SKU>
<PricePer>2.50</PricePer>
<Quantity>1000</Quantity>
<Subtotal>2500.00</Subtotal>
<Description>Deluxe Doohickie</Description>
</Item>
<Item id="4">
<SKU>3256</SKU>
<PricePer>389.00</PricePer>
<Quantity>1</Quantity>
<Subtotal>389.00</Subtotal>
<Description>Muckalucket Bucket</Description>
</Item>
<NumberItems>1111</NumberItems>
<Total>3704.00</Total>
<OrderDate>07/07/2002</OrderDate>
<OrderNumber>8876</OrderNumber>
</Order>
我們使用一個(gè)網(wǎng)絡(luò)表單以訪問這一XML文檔,這一表單將顯示SKU,價(jià)格,數(shù)量,各部分的小計(jì),以及順序中的每一選項(xiàng)的描述。我們的表單還包含向前和向后瀏覽選項(xiàng)的按鈕。
網(wǎng)頁的構(gòu)成
網(wǎng)頁的重要部分是在于表單,我們將使用一個(gè)表以易讀的方式在屏幕上顯示。下面是顯示HTML表的代碼片段:
<form>
<table border="0">
<tr><td>SKU</td><td><input type="text" name="SKU"></td></tr>
<tr><td>Price</td><td><input type="text" name="Price"></td></tr>
<tr><td>Quantity</td><td><input type="text" name="Quantity"></td></tr>
<tr><td>Total</td><td><input type="text" name="Total"></td></tr>
<tr><td>Description</td><td><input type="text"
name="Description"></td></tr>
</table>
<input type="button" value=" << " onClick="getDataPrev();">
<input type="button" value=" >> " onClick="getDataNext();">
</form>
請(qǐng)注意到,我們?cè)诒淼南旅姘藘蓚€(gè)按鈕,即通過getDataNext() 和getDataPrev()函數(shù)來瀏覽前一個(gè)和后一個(gè)的記錄,這也是我們所要討論的問題。
腳本
其實(shí),我們網(wǎng)頁的實(shí)質(zhì)部分不是在于表單,而是在于控制表單的腳本。在我們的腳本中包括四個(gè)部分。首先,我們通過載入XML文檔而初始化網(wǎng)頁。第二部分是導(dǎo)航到下一個(gè)記錄。第三步是導(dǎo)航到前一個(gè)記錄。第四部分是從XML文檔中提取單一的值。表B顯示了我們的網(wǎng)頁的全部內(nèi)容。
表B: jsxml.html
<html>
<head>
<script language="JavaScript">
<!--
vari = -1;
varorderDoc = new ActiveXObject("MSXML2.DOMDocument.3.0");
orderDoc.load("order.xml");
var items = orderDoc.selectNodes("/Order/Item");
function getNode(doc, xpath) {
varretval = "";
var value = doc.selectSingleNode(xpath);
if (value) retval = value.text;
return retval;
}
function getDataNext() {
i++;
if (i > items.length - 1) i = 0;
document.forms[0].SKU.value = getNode(orderDoc, "/Order/Item[" + i + "]/SKU");
document.forms[0].Price.value = getNode(orderDoc, "/Order/Item[" + i + "]/PricePer");
document.forms[0].Quantity.value = getNode(orderDoc, "/Order/Item[" + i + "]/Quantity");
document.forms[0].Total.value = getNode(orderDoc,"/Order/Item[" + i + "]/Subtotal");
document.forms[0].Description.value = getNode(orderDoc, "/Order/Item[" + i + "]/Description");
}
function getDataPrev() {
i--;
if (i < 0) i = items.length - 1;
document.forms[0].SKU.value = getNode(orderDoc, "/Order/Item[" + i + "]/SKU");
document.forms[0].Price.value = getNode(orderDoc,"/Order/Item[" + i + "]/PricePer");
document.forms[0].Quantity.value = getNode(orderDoc, "/Order/Item[" + i + "]/Quantity");
document.forms[0].Total.value = getNode(orderDoc,"/Order/Item["+ i + "]/Subtotal");
document.forms[0].Description.value = getNode(orderDoc, "/Order/Item[" + i + "]/Description");
}
// -->
</script>
</head>
<body onload="getDataNext()">
<h2>XML Order Database</h2>
<form>
<table border="0">
<tr><td>SKU</td><td><input type="text" name="SKU"></td></tr>
<tr><td>Price</td><td><input type="text" name="Price"></td></tr>
<tr><td>Quantity</td><td><input type="text"
name="Quantity"></td></tr>
<tr><td>Total</td><td><input type="text" name="Total"></td></tr>
<tr><td>Description</td><td><input type="text"
name="Description"></td></tr>
</table>
<input type="button" value=" << " onClick="getDataPrev();"> <input type="button" value=" >> " onClick="getDataNext();">
</form>
</body>
</html>
運(yùn)行
這一網(wǎng)頁將傳入并運(yùn)行腳本的初始化。你一定確保order.xml文檔與jsxml.html在相同的相同的路徑上。
初始化部分將一個(gè)新的ActiveX對(duì)象例示為MSXML2.DOMDocument.3.0對(duì)象類型,然后腳本傳入order.xml文檔到內(nèi)存中,并選擇所有的/Order/Item節(jié)點(diǎn)。我們使用/Order/Item節(jié)點(diǎn)以識(shí)別文檔已經(jīng)包含的選項(xiàng)。
文檔中的<body>標(biāo)準(zhǔn)有一個(gè)onLoad屬性,這一屬性能夠使得網(wǎng)頁調(diào)用getDataNext()而初始化。這一功能可用于從XML文檔中獲得下一個(gè)值并顯示在表單中。我們使用一個(gè)簡(jiǎn)單的索引來訪問特定的選項(xiàng)。
向前(>>)和向后(<<)按鈕都使用相同的機(jī)制。首先響應(yīng)onClick事件而調(diào)用getDataNext() 或者getDataPrev(),這兩個(gè)函數(shù)使用了邏輯方法以避免文檔以外的范圍訪問我們的記錄。
最近一個(gè)項(xiàng)目中要用到樹形列表,本來是用mztree的,但數(shù)據(jù)用了xml,本來xml就是樹形目錄,就打算用JavaScript直接解析xml文件了,網(wǎng)上找到一些JavaScript操作xml的方法,在此做一個(gè)總結(jié)。
我的xml文件Login.xml如下:
<?xml version="1.0" encoding="utf-8" ?>
<Login>
<Character>
<C Text="熱血" Value="0"></C>
<C Text="弱氣" Value="1"></C>
<C Text="激情" Value="2"></C>
<C Text="冷靜" Value="3"></C>
<C Text="冷酷" Value="4"></C>
</Character>
<Weapon>
<W Text="光束劍" Value="0"></W>
<W Text="光束配刀" Value="1"></W>
</Weapon>
<EconomyProperty>
<P Text="平均型" Value="0"></P>
<P Text="重視攻擊" Value="1"></P>
<P Text="重視敏捷" Value="2"></P>
<P Text="重視防御" Value="3"></P>
<P Text="重視命中" Value="4"></P>
</EconomyProperty>
</Login>
現(xiàn)在我需要對(duì)這個(gè)xml文件的內(nèi)容進(jìn)行操作。
首先,我們需要加載這個(gè)xml文件,JavaScript中加載xml文件,是通過XMLDOM來進(jìn)行的:
// 加載xml文檔
loadXML = function(xmlFile)
{
var xmlDoc;
if(window.ActiveXObject)
{
xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
xmlDoc.async = false;
xmlDoc.load(xmlFile);
}
else if (document.implementation&&document.implementation.createDocument)
{
xmlDoc = document.implementation.createDocument('', '', null);
xmlDoc.load(xmlFile);
}
else
{
return null;
}
return xmlDoc;
}
xml文件對(duì)象出來了, 接下去我就要對(duì)這個(gè)文檔進(jìn)行操作了。
比如說,我們現(xiàn)在需要得到節(jié)點(diǎn)Login/Weapon/W的第一個(gè)節(jié)點(diǎn)的屬性,那么我們可以如下進(jìn)行:
// 首先對(duì)xml對(duì)象進(jìn)行判斷
checkXMLDocObj = function(xmlFile)
{
var xmlDoc = loadXML(xmlFile);
if(xmlDoc==null)
{
alert('您的瀏覽器不支持xml文件讀取,于是本頁面禁止您的操作,推薦使用IE5.0以上可以解決此問題!');
window.location.href='/Index.aspx';
}
return xmlDoc;
}
// 然后開始獲取需要的Login/Weapon/W的第一個(gè)節(jié)點(diǎn)的屬性值
var xmlDoc = checkXMLDocObj('/EBS/XML/Login.xml');
var v = xmlDoc.getElementsByTagName('Login/Weapon/W')[0].childNodes.getAttribute('Text')
而我在我的程序中的寫法是這樣子的,當(dāng)然我在程序中的寫法是已經(jīng)應(yīng)用到實(shí)際中的了.一并給出來,以供查看。
initializeSelect = function(oid, xPath)
{
var xmlDoc = checkXMLDocObj('/EBS/XML/Login.xml');
var n;
var l;
var e = $(oid);
if(e!=null)
{
n = xmlDoc.getElementsByTagName(xPath)[0].childNodes;
l = n.length;
for(var i=0; i<l; i++)
{
var option = document.createElement('option');
option.value = n[i].getAttribute('Value');
option.innerHTML = n[i].getAttribute('Text');
e.appendChild(option);
}
}
}
上面的訪問代碼中,我們是通過xmlDoc.getElementsByTagName(xPath)來進(jìn)行的。
還可以通過xmlDoc.documentElement.childNodes(1)..childNodes(0).getAttribute('Text')進(jìn)行訪問。
一些常用方法:
◆ xmlDoc.documentElement.childNodes(0).nodeName,可以得到這個(gè)節(jié)點(diǎn)的名稱;
◆ xmlDoc.documentElement.childNodes(0).nodeValue,可以得到這個(gè)節(jié)點(diǎn)的值. 這個(gè)值是來自于這樣子的xml格式:<a>b</b>, 于是可以得到b這個(gè)值;
◆ xmlDoc.documentElement.childNodes(0).hasChild,可以判斷是否有子節(jié)點(diǎn)。
根據(jù)我的經(jīng)驗(yàn),最好是使用getElementsByTagName(xPath)的方法對(duì)節(jié)點(diǎn)進(jìn)行訪問,因?yàn)檫@樣子可以直接通過xPath來定位節(jié)點(diǎn),這樣子會(huì)有更好的性能。
//////////////////////////////////////////////////////////////////////////////////////
function print(){
fso = new ActiveXObject("Scripting.FileSystemObject");
tf = fso.CreateTextFile("E:\\test.ini", true);
tf.WriteLine("要寫入的內(nèi)容");
tf.Close();
}
/////////////////////////////////////////////////////////////////////////////////////
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
namespace Common
{
/// <summary>
/// INI文件讀寫類。
/// </summary>
public class INIFile
{
public string path;
public INIFile(string INIPath)
{
path = INIPath;
}
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section,string key,string val,string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section,string key,string def, StringBuilder retVal,int size,string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath);
/// <summary>
/// 寫INI文件
/// </summary>
/// <param name="Section"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void IniWriteValue(string Section,string Key,string Value)
{
WritePrivateProfileString(Section,Key,Value,this.path);
}
/// <summary>
/// 讀取INI文件
/// </summary>
/// <param name="Section"></param>
/// <param name="Key"></param>
/// <returns></returns>
public string IniReadValue(string Section,string Key)
{
StringBuilder temp = new StringBuilder(255);
int i = GetPrivateProfileString(Section,Key,"",temp, 255, this.path);
return temp.ToString();
}
public byte[] IniReadValues(string section, string key)
{
byte[] temp = new byte[255];
int i = GetPrivateProfileString(section, key, "", temp, 255, this.path);
return temp;
}
/// <summary>
/// 刪除ini文件下所有段落
/// </summary>
public void ClearAllSection()
{
IniWriteValue(null,null,null);
}
/// <summary>
/// 刪除ini文件下personal段落下的所有鍵
/// </summary>
/// <param name="Section"></param>
public void ClearSection(string Section)
{
IniWriteValue(Section,null,null);
}
}
}
#import <msxml3.dll> named_guids //導(dǎo)入動(dòng)態(tài)庫,裝了IE5就有
using namespace MSXML2; //引用命名空間,一般可以把命名空間理解成類和接口的集合,呵呵,對(duì)不對(duì)我也不知道了
#include <vector>
using namespace std;
struct FIELD
{
public:
CString name;
CString type;
CString length;
CString explain;
CString allowNull;
CString autoIncrease;
};
class Xml
{
public:
Xml(void);
~Xml(void);
private:
HRESULT hr;
MSXML2::IXMLDOMDocumentPtr pDoc; //XML文檔接口指針
public:
void AddKey(CString moduleName,CString keyName, CString keyValue);
CString ReadKeyValue(CString moduleName, CString keyName);
private:
void NewDocument(CString moduleName, CString keyName, CString keyValue);
public:
bool ReadTable(CTreeCtrl * tree);
bool ReadFields(CString tableName,vector<FIELD> &fields);
bool SaveTable(vector<FIELD> fields,CString tableName,bool bNew);
};
//-------------------------------------------------------------------------------------------------------------------------------------
上面是頭文件,這是cpp文件
#include "StdAfx.h"
#include "xml.h"
Xml::Xml(void)
{
CoInitialize(NULL); //初始化COM
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMDocument,(void**)&pDoc); //創(chuàng)建XML文檔實(shí)例
}
Xml::~Xml(void)
{
CoUninitialize();
}
void Xml::AddKey(CString moduleName,CString keyName, CString keyValue)
{
CString selectString="AppSetting/"+moduleName; //XML節(jié)點(diǎn)定位字符串,定位到節(jié)點(diǎn)名為moduleName的二級(jí)節(jié)點(diǎn),根節(jié)點(diǎn)取默認(rèn)名為"AppSetting"
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMDocument,(void**)&pDoc); //創(chuàng)建文檔實(shí)例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("Config.xml")) //查找文件是否存在,不存在則調(diào)用函數(shù)生成一個(gè)新的XML文件
{
NewDocument(moduleName,keyName,keyValue);
return;
}
pDoc->load("Config.xml"); //從應(yīng)用程序目錄中加載XML文件
MSXML2::IXMLDOMNodePtr moduleNode; //XML節(jié)點(diǎn)接口指針
MSXML2::IXMLDOMNodePtr keyNode; //同上
MSXML2::IXMLDOMNodePtr selectNode; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNode,(void**)&moduleNode); //創(chuàng)建節(jié)點(diǎn)實(shí)例
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNode,(void**)&keyNode); //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNode,(void**)&selectNode); //同上
moduleNode=pDoc->selectSingleNode((_bstr_t)selectString); //定位到節(jié)點(diǎn)名為moduleName的二級(jí)節(jié)點(diǎn)
if(moduleNode==NULL) //如果無法定位,說明還不存在此節(jié)點(diǎn),生成一個(gè)新的節(jié)點(diǎn)
{
selectNode=pDoc->selectSingleNode("AppSetting"); //定位到根節(jié)點(diǎn),這里一定能定位成功,除非手動(dòng)改了XML文件
moduleNode=pDoc->createNode(1,(_bstr_t)moduleName,""); //生成新節(jié)點(diǎn)
selectNode->appendChild(moduleNode); //將新節(jié)點(diǎn)添加到根節(jié)點(diǎn)
}
selectString+="/"+keyName; //XML節(jié)點(diǎn)定位字符串,定位到節(jié)點(diǎn)名為keyName的三級(jí)節(jié)點(diǎn)
keyNode=pDoc->selectSingleNode((_bstr_t)selectString); //定位到節(jié)點(diǎn)名為keyName的三級(jí)節(jié)點(diǎn)
if(keyNode==NULL) //如果無法定位,說明還不存在此節(jié)點(diǎn),生成一個(gè)新的節(jié)點(diǎn)
{
keyNode=pDoc->createNode(1,(_bstr_t)keyName,""); //生成新節(jié)點(diǎn)
moduleNode->appendChild(keyNode); //將新節(jié)點(diǎn)添加到節(jié)點(diǎn)名moduleName的節(jié)點(diǎn)
}
keyNode->text=(_bstr_t)keyValue; //給節(jié)點(diǎn)名為keyName的節(jié)點(diǎn)賦text值秋keyValue
pDoc->save("Config.xml"); //保存
}
CString Xml::ReadKeyValue(CString moduleName, CString keyName)
{
CString selectString="AppSetting/"+moduleName+"/"+keyName;
CString keyValue="";
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMDocument,(void**)&pDoc); //創(chuàng)建文檔實(shí)例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("Config.xml")) //查找文件是否存在,不存在則調(diào)用函數(shù)生成一個(gè)新的XML文件
{
return "";
}
pDoc->load("Config.xml");
MSXML2::IXMLDOMNodePtr selectNode; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNode,(void**)&selectNode); //創(chuàng)建節(jié)點(diǎn)實(shí)例
selectNode=pDoc->selectSingleNode((_bstr_t)selectString);
if(selectNode==NULL)
{
return "";
}
else
{
return (CString)((BSTR)selectNode->text);
}
}
void Xml::NewDocument(CString moduleName, CString keyName, CString keyValue)
{
CString strXml="<AppSetting><"+moduleName+"><"+keyName+">"+keyValue+"</"+keyName+"></"+moduleName+"></AppSetting>"; //XML字符串
pDoc->loadXML((_bstr_t)strXml); //通過加載字符生成XML的Document,此處用方法loadXml,從文件加載用load,參考前面
pDoc->save("Config.xml"); //保存
}
bool Xml::ReadTable(CTreeCtrl * tree)
{
CString selectString="DataResource/Tables/Table";
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMDocument,(void**)&pDoc); //創(chuàng)建文檔實(shí)例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("DataResource.xml")) //查找文件是否存在,不存在則調(diào)用函數(shù)生成一個(gè)新的XML文件
{
return false;
}
pDoc->load("DataResource.xml");
MSXML2::IXMLDOMElementPtr node; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMElement,(void**)&node); //創(chuàng)建節(jié)點(diǎn)實(shí)例
MSXML2::IXMLDOMNodeListPtr selectNodes;
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNodeList,(void**)&selectNodes);//創(chuàng)建節(jié)點(diǎn)列表實(shí)例
selectNodes=pDoc->selectNodes((_bstr_t)selectString); //查找節(jié)點(diǎn)集
HTREEITEM tabItem=tree->GetChildItem(tree->GetRootItem());
if(selectNodes==NULL)
{
return false;
}
else
{
for(long i=0;i<selectNodes->Getlength();i++)
{
node=selectNodes->Getitem(i);
_variant_t nodeName=node->getAttribute("Name");
tree->InsertItem((CString)nodeName.bstrVal,3,3,tabItem);
}
//return (CString)((BSTR)selectNode->text);
}
return true;
}
bool Xml::ReadFields(CString tableName,vector<FIELD> &fields)
{
CString selectString="DataResource/Tables/Table";
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMDocument,(void**)&pDoc); //創(chuàng)建文檔實(shí)例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("DataResource.xml")) //查找文件是否存在,不存在則調(diào)用函數(shù)生成一個(gè)新的XML文件
{
return false;
}
pDoc->load("DataResource.xml");
MSXML2::IXMLDOMElementPtr node; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMElement,(void**)&node); //創(chuàng)建節(jié)點(diǎn)實(shí)例
MSXML2::IXMLDOMNodeListPtr tableNodes;
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNodeList,(void**)&tableNodes);//創(chuàng)建節(jié)點(diǎn)列表實(shí)例
MSXML2::IXMLDOMNodeListPtr fieldNodes;
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNodeList,(void**)&fieldNodes);//創(chuàng)建節(jié)點(diǎn)列表實(shí)例
tableNodes=pDoc->selectNodes((_bstr_t)selectString); //查找節(jié)點(diǎn)集
if(tableNodes==NULL)
{
return false;
}
for(long i=0;i<tableNodes->Getlength();i++)
{
node=tableNodes->Getitem(i);
CString nodeName=(CString)node->getAttribute("Name");
if(nodeName==tableName)
{
fieldNodes=node->GetchildNodes();
break;
}
}
if(fieldNodes==NULL)
{
return false;
}
fields.clear();
for(long i=0;i<fieldNodes->Getlength();i++)
{
FIELD field;
node=fieldNodes->Getitem(i);
field.autoIncrease=node->getAttribute("AutoIncrease");
field.explain=node->getAttribute("Explain");
field.length=node->getAttribute("Length");
field.name=node->getAttribute("Name");
field.type=node->getAttribute("Type");
field.allowNull=node->getAttribute("AllowNull");
fields.push_back(field);
}
return true;
}
bool Xml::SaveTable(vector<FIELD> fields,CString tableName,bool bNew)
{
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMDocument,(void**)&pDoc); //創(chuàng)建文檔實(shí)例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("DataResource.xml")) //查找文件是否存在,不存在則調(diào)用函數(shù)生成一個(gè)新的XML文件
{
return false;
}
pDoc->load("DataResource.xml");
CString selectString="";
selectString="DataResource/Tables";
MSXML2::IXMLDOMNodePtr tablesNode;
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNode,(void**)&tablesNode); //創(chuàng)建節(jié)點(diǎn)實(shí)例
MSXML2::IXMLDOMElementPtr tableNode; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMElement,(void**)&tableNode); //創(chuàng)建節(jié)點(diǎn)實(shí)例
tablesNode=pDoc->selectSingleNode((_bstr_t)selectString); //查找節(jié)點(diǎn)集
if(bNew)
{
tableNode=pDoc->createNode(1,"Table","");
tableNode->setAttribute("Name",(_bstr_t)tableName);
}
else
{
MSXML2::IXMLDOMNodeListPtr tableNodeList;
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNodeList,(void**)&tableNodeList); //創(chuàng)建節(jié)點(diǎn)列表實(shí)例
tableNodeList=tablesNode->GetchildNodes();
CString nodeName="";
for(int i=0;i<tableNodeList->Getlength();i++)
{
tableNode=tableNodeList->Getitem(i);
nodeName=tableNode->getAttribute("Name");
if(nodeName.MakeLower()==tableName.MakeLower())
{
MSXML2::IXMLDOMElementPtr fieldNode; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMElement,(void**)&fieldNode); //創(chuàng)建節(jié)點(diǎn)實(shí)例
int fieldsCount=tableNode->GetchildNodes()->Getlength();
for(int j=fieldsCount-1;j>-1;j--)
{
fieldNode=tableNode->GetchildNodes()->Getitem(j);
tableNode->removeChild(fieldNode);
}
break;
}
if(i==tableNodeList->Getlength())
{
return false;
}
}
}
for(int i=0;i<fields.size();i++)
{
MSXML2::IXMLDOMElementPtr fieldNode; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMElement,(void**)&fieldNode); //創(chuàng)建節(jié)點(diǎn)實(shí)例
fieldNode=pDoc->createNode(1,"Field","");
FIELD field=fields[i];
fieldNode->setAttribute("Name",(_bstr_t)field.name);
fieldNode->setAttribute((_bstr_t)"AllowNull",(_bstr_t)field.allowNull);
fieldNode->setAttribute((_bstr_t)"AutoIncrease",(_bstr_t)field.autoIncrease);
fieldNode->setAttribute((_bstr_t)"Explain",(_bstr_t)field.explain);
fieldNode->setAttribute((_bstr_t)"Length",(_bstr_t)field.length);
fieldNode->setAttribute((_bstr_t)"Type",(_bstr_t)field.type);
tableNode->appendChild(fieldNode);
}
if(bNew)
tablesNode->appendChild(tableNode);
pDoc->save("DataResource.xml");
return true;
}
//下面是另外的一段代碼
{
// TODO: Add your implementation code here
CComPtr<xml::IXMLDOMDocument> pDoc;
try
{
HRESULT hr = pDoc.CoCreateInstance(L"Msxml2.DOMDocument.4.0");
if (FAILED(hr)) return hr;
CComPtr<xml::IXMLDOMElement> pRoot;
hr = pDoc->get_documentElement(&pRoot);
if (FAILED(hr)) return hr;
//create comment
CComPtr<xml::IXMLDOMComment> pComm;
hr=pDoc->createComment(CComBSTR(L"Compupacific Entry Template"),&pComm);
if (FAILED(hr)) return hr;
hr=pDoc->appendChild(pComm,0);
//Root of the Doc
CComPtr<xml::IXMLDOMElement> pElem;
hr = pDoc->createElement(CComBSTR(L"Template"), &pElem);
if (FAILED(hr)) return hr;
hr = pDoc->putref_documentElement(pElem);
if (FAILED(hr)) return hr;
VARIANT var;
var.vt=VT_BSTR;
var.bstrVal=::SysAllocString(m_bstrCaption);
hr = pElem->setAttribute(CComBSTR(L"Name"), var);
::SysFreeString(var.bstrVal);
if (FAILED(hr)) return hr;
VARIANT var1;
var1.vt=VT_BSTR;
var1.bstrVal=::SysAllocString(m_bstrSampleImage);
hr = pElem->setAttribute(CComBSTR(L"Sample"), var1);
::SysFreeString(var1.bstrVal);
if (FAILED(hr)) return hr;
VARIANT var2;
var2.vt=VT_I2;
var2.iVal=m_shDock;
hr = pElem->setAttribute(CComBSTR(L"Dock"), var2);
if (FAILED(hr)) return hr;
}
catch(...)
{
::MessageBox(NULL,_T("Error in save form property!"),_T("Error Report"),MB_OK);
return S_FALSE;
}
try
{
//Now tell the form to persist its child controls
CComBSTR Tmp;
for(std::list<CAxWindowHandle* >::iterator it = m_listSites.begin(); it != m_listSites.end();it++)
{
if(*it)
{
CComPtr<xml::IXMLDOMElement> pRoot;
HRESULT hr = pDoc->get_documentElement(&pRoot);
if (FAILED(hr)) return hr;
CComPtr<xml::IXMLDOMNode> pNode;
Tmp=OLESTR("Control");
CComBSTR Tmp1;
hr = pDoc->createNode(CComVariant(1),Tmp.m_str, Tmp1.m_str, &pNode);
if (FAILED(hr)) return hr;
hr = pRoot->appendChild(pNode.p, 0);
if (FAILED(hr)) return hr;
CComPtr<IPersistPropertyBag> spPersistPropBag;
hr = (*it)->QueryControl(&spPersistPropBag);
if (FAILED(hr)) return hr;
hr = spPersistPropBag->InitNew();
if (FAILED(hr)) return hr;
CComPtr<IPersistPropertyBag> spExtendedPPB;
if((*it)->m_pExtendedDispatchObj)
{
hr = (*it)->m_pExtendedDispatchObj->QueryInterface(&spExtendedPPB);
if (FAILED(hr)) return hr;
}
CComQIPtr<xml::IXMLDOMElement> pElem(pNode);
if(!pElem) return E_NOINTERFACE;
//Save Extended Properties
hr = SaveToXML(pDoc, pElem.p, spExtendedPPB, TRUE, TRUE);
if (FAILED(hr)) return hr;
//Save Native Properties
hr = SaveToXML(pDoc, pElem.p, spPersistPropBag, TRUE, TRUE);
if (FAILED(hr)) return hr;
}
}
return pDoc->save(CComVariant(FileName));
}
catch(...)
{
::MessageBox(NULL,_T("Error in save control property!"),_T("Error Report"),MB_OK);
return S_FALSE;
}
}
1.徹底關(guān)閉Excel進(jìn)程
rang.ReleaseDispath();
sheet.ReleaseDispath();
sheets.ReleaseDispath();
book.ReleaseDispath();
books.ReleaseDispath();
ExcelApp.Quit();//ExcelApp,是_Applacation對(duì)象,以上幾個(gè)對(duì)象同理。
ExcelApp.ReleaseDispath();
注意:最后兩行代碼順序不要反了,否則不能徹底關(guān)閉Excel進(jìn)程,這是關(guān)鍵
2.將Excel文件保存為HTML網(wǎng)頁
sheet.SaveAs(strFileName,ColeVariant((long)44),vtMissing,...后面參數(shù)全是vtMissing);
sheet.SaveAs(strFileName,vtMissing,vtMissing,...后面參數(shù)全是vtMissing);
3.不顯示任何警告對(duì)話框
在保存文件代碼之前加上下面語句
ExcelApp.SetAlertBeforeOverwritting(false);
ExcelApp.SetDisplayAlert(false);
在開發(fā)軟件時(shí),經(jīng)常要將數(shù)據(jù)輸出到Excel 2000中,在Excel 2000中對(duì)該數(shù)據(jù)進(jìn)行進(jìn)一步地格式化處理或進(jìn)行計(jì)算處理。在Visual Basic中處理起來較簡(jiǎn)單,Excel 2000的VB編程幫助中有較為詳細(xì)的介紹。在Visual C++中如何進(jìn)行處理了?利用Excel 2000的ActiveX Automate功能,處理起來同VB中類似。但要注意以下幾點(diǎn):
對(duì)于對(duì)象的屬性值的讀取或賦值,需要用GetProperty()或SetProperty(NewValue)函數(shù),不能象VB中直接通過屬性名稱取值或賦值。例如:Worksheet.GetCount(), Worksheet.SetName(“Sheet1”)。 |
對(duì)集合對(duì)象中的成員對(duì)象的引用,必須使用集合對(duì)象的GetItem()函數(shù)。例如:Worksheets.GetItem(ColeVariant((long)1))或Worksheets.GetItem(ColeVariant(“Sheet1”))取得第一個(gè)工作表。 |
在COM接口中,時(shí)常用到Variant,BSTR,SafeArray數(shù)據(jù)類型。Variant數(shù)據(jù)類型是一個(gè)聯(lián)合,可表示幾乎所有的類型的數(shù)據(jù),具體用法見MSDN中的相關(guān)介紹,類_variant_t是對(duì)VARIANT數(shù)據(jù)類型的封裝。在Excel 2000的VB編程幫助中,如果提到某函數(shù)或?qū)傩孕枰粋€(gè)值,該值的數(shù)據(jù)類型通常是Variant,在封裝Excel 2000對(duì)象的類定義中,說明了具體需要的數(shù)據(jù)類型。BSTR是一個(gè)包括了字符串和字符串長度的數(shù)據(jù)結(jié)構(gòu),類_bstr_t是對(duì)BSTR數(shù)據(jù)類型的封裝。在Excel 2000的VB編程幫助中提到的字符串通常指BSTR。具體函數(shù)參數(shù)或?qū)傩缘臄?shù)據(jù)類型,見封裝該對(duì)象的類的定義。SafeArray是一個(gè)包括數(shù)組和數(shù)組邊界的結(jié)構(gòu),數(shù)組邊界外的內(nèi)容不允許訪問。在Excel 2000的VB編程幫助中提到的數(shù)組是指SafeArray。關(guān)于SafeArray的處理,請(qǐng)見MSDN的相關(guān)幫助。 |
對(duì)于缺省參數(shù)和缺省值。在VB中,函數(shù)的參數(shù)可以空缺,在VC++中不允許,必須將所有的參數(shù)填寫完全。如果你希望指定某個(gè)參數(shù)為缺省值,根據(jù)參數(shù)數(shù)據(jù)類型的不同,可指定不同的缺省值。當(dāng)參數(shù)數(shù)據(jù)類型為字符串時(shí),可以用長度為0的字符串。如果參數(shù)是Variant類型,可用常量vtMissing,該常量在comdef.h中定義。也可用_variant_t(DISP_E_PARAMNOTFOUND, VT_ERROR)產(chǎn)生一個(gè)Variant對(duì)象。 |
Excel對(duì)象中的集合對(duì)象有時(shí)包括的子對(duì)象是不一定的,例如:Range對(duì)象,可以表示Cell的集合,也可以表示Column的集合或Row的集合,Range.GetItem(1)可以返回Cell或Column或Row對(duì)象。 |
對(duì)對(duì)象的引用或傳遞對(duì)象,使用IDispatch類對(duì)象,有時(shí)利用Variant對(duì)IDispatch進(jìn)行包裝。 |
以下是一段源程序,演示如何啟動(dòng)Excel 2000,利用一個(gè)模板文件產(chǎn)生一個(gè)新文檔,在該文檔的”Sheet1”工作表的第一個(gè)單元中填寫一段文字,設(shè)置第一列的列寬,然后調(diào)用一個(gè)模板中的宏,執(zhí)行一段程序,最后打印預(yù)覽該Excel文檔。模板文件名稱:MyTemplate.xlt。程序在Visual C++ 6.0 sp4,Windows 2000 Professional sp-1下調(diào)試通過。 |
首先利用Visual C++ 6.0,建立一個(gè)MFC基于對(duì)話框的工程項(xiàng)目,共享DLL,Win32平臺(tái)。工程名稱ExcelTest。在主對(duì)話框中加入一個(gè)按鈕, |
雙擊該按鈕,增加成員函數(shù)void CExcelTestDlg::OnExceltest()。 |
在BOOL CExcelTestApp::InitInstance()中,dlg.DoModal();之前增加代碼: |
if (CoInitialize(NULL)!=0) |
AfxMessageBox("初始化COM支持庫失敗!"); |
選擇Menu->View->ClassWizade,打開ClassWizade窗口,選擇Add Class->From a type library,選擇D:\Program Files\Microsoft Office\office\Excel9.OLB(D:\Program Files\Microsoft Office\是本機(jī)上Microsoft Office 2000的安裝目錄,可根據(jù)個(gè)人機(jī)器上的實(shí)際安裝目錄修改)。選擇_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range,加入新類,分別為_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range,頭文件Excel9.h,源文件Excel9.cpp。 |
在ExcelTestDlg.cpp文件的頭部,#include "ExcelTestDlg.h"語句之下,增加 : |
在void CExcelTestDlg::OnExceltest() 函數(shù)中增加如下代碼: |
void CExcelTestDlg::OnExceltest() |
//創(chuàng)建Excel 2000服務(wù)器(啟動(dòng)Excel) |
if (!ExcelApp.CreateDispatch("Excel.Application",NULL)) |
AfxMessageBox("創(chuàng)建Excel服務(wù)失敗!"); |
wbsMyBooks.AttachDispatch(ExcelApp.GetWorkbooks(),true); |
wbMyBook.AttachDispatch(wbsMyBooks.Add(_variant_t("g:\\exceltest\\MyTemplate.xlt"))); |
wssMysheets.AttachDispatch(wbMyBook.GetWorksheets(),true); |
wsMysheet.AttachDispatch(wssMysheets.GetItem(_variant_t("sheet1")),true); |
//得到全部Cells,此時(shí),rgMyRge是cells的集合 |
rgMyRge.AttachDispatch(wsMysheet.GetCells(),true); |
rgMyRge.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t("This Is A Excel Test Program!")); |
rgMyRge.AttachDispatch(wsMysheet.GetColumns(),true); |
rgMyRge.AttachDispatch(rgMyRge.GetItem(_variant_t((long)1),vtMissing).pdispVal,true); |
rgMyRge.SetColumnWidth(_variant_t((long)200)); |
ExcelApp.Run(_variant_t("CopyRow"),_variant_t((long)10),vtMissing,vtMissing, |
vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing, |
vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing, |
vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing, |
vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing); |
ExcelApp.SetVisible(true); |
wbMyBook.PrintPreview(_variant_t(false)); |
rgMyRge.ReleaseDispatch(); |
wsMysheet.ReleaseDispatch(); |
wssMysheets.ReleaseDispatch(); |
wbMyBook.ReleaseDispatch(); |
wbsMyBooks.ReleaseDispatch(); |
ExcelApp.ReleaseDispatch(); |
添加完以上程序后,可運(yùn)行看結(jié)果。 |
如何自動(dòng)執(zhí)行將 Excel 工作表保存為 HTML 文件中使用 Visual c + +
http://support.microsoft.com/kb/199691/zh-cn
VC操作Excel,當(dāng)用SaveAs保存Excel時(shí),如果待保存路徑下已經(jīng)存在該Excel,則會(huì)彈出一個(gè)對(duì)話框提示你當(dāng)前路徑下已經(jīng)存在該Excel,是否替換,下面有三個(gè)按鈕:“是”、“否”、“取消”。如果選擇了“取消”則會(huì)彈出一個(gè)錯(cuò)誤警告對(duì)話框。
可以按照如下方法解決這個(gè)問題:在SaveAs之前添加代碼: _Application ExcelApp; ExcelApp.SetAlertBeforeOverwriting(FALSE); ExcelApp.SetDisplayAlerts(FALSE);
在Office2003版Office所生成的Excel.cpp文件中,類_Workbook的SaveAs函數(shù),其函數(shù)原型如下: void SaveAs(const VARIANT& Filename, const VARIANT& FileFormat, const VARIANT& Password, const VARIANT& WriteResPassword, const VARIANT& ReadOnlyRecommended, const VARIANT& CreateBackup, long AccessMode, const VARIANT& ConflictResolution, const VARIANT& AddToMru, const VARIANT& TextCodepage, const VARIANT& TextVisualLayout, const VARIANT& Local);
參數(shù)含義參考如下: Question: Nothing like trying to learn/teach yourself something new to make you humble. Winbatch 99p, Excel 97. I'm loading a tab delimited file {M:\somedir\myfile.txt} into Excel using OLE to manipulate it some & want to save it as an Excel .xls file {M:\somedir\myfile.txt}. I can get the file to save under the new name, i.e. with the .xls extension but it's still in tab delimited format, NOT Excel's native file format. The following is from a macro I recorded while doing the action I want to automate: ActiveWorkbook.SaveAs FileName:="M:\TMI_Data\Processed\FEB00.xls", FileFormat:=xlNormal, Password:="", WriteResPassword:="", ReadOnlyRecommended:=False, CreateBackup:=False I can get the following code to save the file and add the filename to the MRU list. fileXL ="M:\TMI_Data\Processed\FEB00.xls" Awkbk=ObjXL.ActiveWorkbook savefile=Awkbk.SaveAs (fileXL) ; this works OR savefile=Awkbk.SaveAs ( fileXL, , , , , ,@True ) ; this works the @True adds the file to the MRU list. But, whenever I try to insert something in the position that I think the fileformat stuff is supposed to go I get 1261 OLE exception errors or 3250 OLE Object error : Problem occurred formatting parameters. I'm wondering if it's a Named parameter ? If I'm understanding the docs correctly (big IF) a named parameter would go after all the positional parameters ? T/F ? I've tried a lot of permutations & combinations & haven't stumbled up on something that'll work yet. How does one differentiate between /tell one from the other on Named vice positional parameters ? I've looked in the VBA help & haven't stumbled onto anything. Answer: Sounds like you almost have it. Positional parameters first, then the :: then the parameter=value pairs for the named parameters. Question (cont'd): I'm just not grasping something here. I've tried the line : savefile=Awkbk.SaveAs ( fileXL, , , , , , , , , , ::FileFormat = "xlNormal") with 0 to 10 commas for "positional parameters" between the "fileXL" & the "::". With 0 or 1 comma I get 1261 OLE exception Error & the following entry from wwwbatch.ini [OLE Exception] Microsoft Excel=Unable to get the SaveAs property of the Workbook class With 2 to 10 commas I get NO ERRORS, BUT while it saves with an .xls extension it is still Tab delimited. How can you tell if a parameter is a "Named Parameter" ? The VBA docs make the stuff all look like "Positional parameters" Answer: Maybe there are three required parameters? Maybe xlNormal is not a tring but a constant and we have to figure out what number it is? Maybe cut and paste the SaveAs documentation here and we can stare at it. Bit of an OLE tip that I found a bit by accident. If you want to know whether something is a string or a constant, do it in VBA - in this case, something like var=xlNormal If it bombs out, it's a string. If it doesn't, it'll return a value for you to plug into your scripts. Here's the docs for the "SaveAs Method" clipped direct from the VBA help : Saves changes to the sheet (Syntax 1) or workbook (Syntax 2) in a different file. Syntax 1 expression.SaveAs(Filename, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, AddToMru, TextCodePage, TextVisualLayout) Syntax 2 expression.SaveAs(Filename, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, AccessMode, ConflictResolution, AddToMru, TextCodePage, TextVisualLayout) expression Required. An expression that returns a Chart or Worksheet object (Syntax 1) or a Workbook object (Syntax 2). Filename Optional Variant. A string that indicates the name of the file to be saved. You can include a full path; if you don't, Microsoft Excel saves the file in the current folder. FileFormat Optional Variant. The file format to use when you save the file. For a list of valid choices, see the FileFormat property. Password Optional Variant. A case-sensitive string (no more than 15 characters) that indicates the protection password to be given to the file. WriteResPassword Optional Variant. A string that indicates the write-reservation password for this file. If a file is saved with the password and the password isn't supplied when the file is opened, the file is opened as read-only. ReadOnlyRecommended Optional Variant. True to display a message when the file is opened, recommending that the file be opened as read-only. CreateBackup Optional Variant. True to create a backup file. AccessMode Optional Variant. The workbook access mode. Can be one of the following XlSaveAsAccessMode constants: xlShared (shared list), xlExclusive (exclusive mode), or xlNoChange (don't change the access mode). If this argument is omitted, the access mode isn't changed. This argument is ignored if you save a shared list without changing the file name. To change the access mode, use the ExclusiveAccess method. ConflictResolution Optional Variant. Specifies the way change conflicts are resolved if the workbook is a shared list. Can be one of the following XlSaveConflictResolution constants: xlUserResolution (display the conflict-resolution dialog box), xlLocalSessionChanges (automatically accept the local user's changes), or xlOtherSessionChanges (accept other changes instead of the local user's changes). If this argument is omitted, the conflict-resolution dialog box is displayed. AddToMru Optional Variant. True to add this workbook to the list of recently used files. The default value is False. TextCodePage Optional Variant. Not used in U.S. English Microsoft Excel. TextVisualLayout Optional Variant. Not used in U.S. English Microsoft Excel. Resolution: GREAT Tip -- I inserted your line into the macro & then stepped thru it. It returned a value of -4143. I plugged it into the command like so: savefile=Awkbk.SaveAs ( fileXL, -4143 , , , , ,@True ) and SHAZAM it works ! It would have been A WHILE before I'd have stumbled on to that. Thanks Again.
參考鏈接: http://topic.csdn.net/t/20050121/15/3743958.html http://topic.csdn.net/t/20050324/11/3876932.html
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
本人參考網(wǎng)上做法,利用模板實(shí)現(xiàn)了VC對(duì)EXCEL的操作,但是存在以下問題:
1.第一次運(yùn)行程序,點(diǎn)擊保存時(shí)沒問題,當(dāng)?shù)诙芜\(yùn)行程序時(shí),會(huì)彈出對(duì)話框,提示已經(jīng)存在文件,是否替換(是、否、取消),當(dāng)點(diǎn)擊“否”的時(shí)候會(huì)彈出警告對(duì)話框,程序中斷;
2.程序運(yùn)行后,第一次點(diǎn)擊保存時(shí),不會(huì)出錯(cuò),接著再次點(diǎn)擊保存時(shí),就會(huì)出現(xiàn)警告:無法找到模板......;即程序運(yùn)行后不能實(shí)現(xiàn)多次保存。
3.程序在關(guān)閉后,為何在任務(wù)管理器的進(jìn)程里并沒有結(jié)束,即不能實(shí)現(xiàn)程序在后臺(tái)也關(guān)閉。
以下是源代碼,有勞哪位大俠解惑!不勝感激!
void CTEST::OnConnect()
{
// TODO: Add your control notification handler code here
_Application _app;
_Workbook _workBook;
_Worksheet _workSheet;
Worksheets workSheets;
Workbooks workBooks;
Range range;
_Application ExcelApp;
ExcelApp.SetAlertBeforeOverwriting(FALSE);
ExcelApp.SetDisplayAlerts(FALSE);
// LPDISPATCH lpDisp;
char path[MAX_PATH];
//VARIANT _variant_t;
if (CoInitialize(NULL) != 0)
{
AfxMessageBox("初始化COM支持庫失敗!");
exit(1);
}
if(!_app.CreateDispatch("Excel.Application", NULL))
{
MessageBox("創(chuàng)建Excel服務(wù)失敗!", "信息提示", MB_OK);
return ;
}
//利用模板建立新文檔
_app.SetUserControl(true);
//_app.SetVisible(true);
CFileDialog fileDlg(false);
fileDlg.m_ofn.lpstrFilter="Text Files(*.xls)\0ALL Files(*.*)\0*.*\0\0";
fileDlg.m_ofn.lpstrDefExt="xls";
GetCurrentDirectory(MAX_PATH,path);
CString strPath=path;
CString Path,Name;
strPath+="\\模板";
workBooks=_app.GetWorkbooks();
_workBook=workBooks.Add(_variant_t(strPath));
workSheets=_workBook.GetWorksheets();
_workSheet=workSheets.GetItem(COleVariant((short)1));
range=_workSheet.GetCells();
range.SetItem(_variant_t((long)1), _variant_t((long)3), _variant_t("寫入數(shù)據(jù)了"));
range.SetItem(_variant_t((long)2), _variant_t((long)3), _variant_t("寫入數(shù)據(jù)了"));
range.SetItem(_variant_t((long)3), _variant_t((long)3), _variant_t("寫入數(shù)據(jù)了"));
range.SetItem(_variant_t((long)4), _variant_t((long)3), _variant_t("寫入數(shù)據(jù)了"));
if(IDOK==fileDlg.DoModal())//這里實(shí)現(xiàn)“另存為”對(duì)話框
{
Path=fileDlg.GetPathName();
Name=fileDlg.GetFileName();
//保存數(shù)據(jù)
_workSheet.SaveAs(Path,vtMissing,vtMissing,vtMissing,vtMissing,
vtMissing,vtMissing,vtMissing,vtMissing,vtMissing);
///////////////////////////////////////////////////////////////////////////////////////////////////
}
range.ReleaseDispatch();
_workSheet.ReleaseDispatch();
workSheets.ReleaseDispatch();
_workBook.ReleaseDispatch();
workSheets.ReleaseDispatch();
_app.ReleaseDispatch();
_workBook.Close(vtMissing,COleVariant(Path),vtMissing);
workBooks.Close();
_app.Quit();
CoUninitialize();
}
以上幾個(gè)問題已經(jīng)解決,倒騰了一晚上。
(1)將char path[MAX_PATH];
GetCurrentDirectory(MAX_PATH,path);
CString strPath=path;定義成全局變量,
(2)workBook.Close(vtMissing,COleVariant(Path),vtMissing);
改成_ COleVariant aver((long)DISP_E_PARAMNOTFOUND, VT_ERROR); workBook.Close(aver,COleVariant(Path),aver);
這樣的話問題就解決了。
今天終于安裝了一個(gè)Visual Studio 2005 Team Suite簡(jiǎn)體中文版,新建立了個(gè)工程感覺速度比2003快很多,而且界面設(shè)置功能也強(qiáng)大了很多,內(nèi)置XP風(fēng)格菜單和工具條。打包時(shí)可以自動(dòng)檢測(cè).NET Framework 2.0并將其集成到安裝包,而不像2003需要安裝引導(dǎo)程序插件PluginInstaller.msi才能做到這一點(diǎn)。
就是不知道目前的GIS開發(fā)工具能不能用在2005的開發(fā)環(huán)境中。
如果已經(jīng)完成了項(xiàng)目的開發(fā)就需要進(jìn)行打包分發(fā)。下面將2005下的打包分發(fā)進(jìn)行簡(jiǎn)單介紹
開發(fā)過程和2003雷同,主要介紹打包過程。(以VisualBasic為例,項(xiàng)目名稱為MyPrj)
1、在開發(fā)完成的項(xiàng)目工程MyPrj中,文件-〉添加-〉新建項(xiàng)目,在添加新項(xiàng)目對(duì)話框中選擇其他項(xiàng)目類型-安裝和部署,在模板中選擇安裝項(xiàng)目并取名SetupMyPrj
2、解決方案資源管理器中選擇SetupMyPrj雙擊,從文件系統(tǒng)(SetupMyPrj)中的“目標(biāo)計(jì)算機(jī)上的文件系統(tǒng)”選擇"應(yīng)用程序文件夾"單擊右鍵,添加“項(xiàng)目輸出”,選擇主輸出,確定后即產(chǎn)生“主輸出來自MyPrj(活動(dòng))”的字樣,同時(shí)具有相關(guān)的依賴項(xiàng)文件。
3、按照需求添加用戶的程序菜單和用戶桌面快捷方式。
在“主輸出來自MyPrj(活動(dòng))”單擊右鍵,選擇“創(chuàng)建 主輸出來自MyPrj(活動(dòng)) 的快捷方式”,創(chuàng)建后,重命名為“MyPrj”,然后拖動(dòng)到“用戶桌面”的文件夾下。這樣的話,安裝后,在用戶桌面上就存在應(yīng)用程序的快捷方式了。此處可以同過快捷方式的屬性來制定快捷方式的圖標(biāo)。
創(chuàng)建 “用戶的'程序'菜單”快捷方式,再重復(fù)上面的操作即可。將創(chuàng)建的快捷方式拖到“用戶的'程序'菜單”文件夾下。
4、一般開發(fā)軟件都要有軟件的卸載功能,這個(gè)可通過Windows的msiexec.exe實(shí)現(xiàn)。選擇SetupMyPrj,右鍵,選擇“添加文件”,瀏覽到系統(tǒng)安裝盤下的msiexec.exe,(一般路徑為 c:\windows\system32\msiexec.exe),添加到你的方案里面,此刻該程序會(huì)在"應(yīng)用程序文件夾"出現(xiàn),右鍵,選擇“創(chuàng)建msiexec.exe快捷方式”,命名為“卸載MyPrj”,然后拖到“用戶的'程序'菜單”即可。最后要在該快捷方式的Arguments 屬性里面寫入“/x {ProductID}”,ProductID是你創(chuàng)建的項(xiàng)目的Product Code,主要不要有引號(hào)。此時(shí),卸載功能完成,當(dāng)然你也可以為卸載菜單指定一個(gè)個(gè)性圖標(biāo)。
5、為了避免目標(biāo)計(jì)算機(jī)沒有程序運(yùn)行需求的.net framework2.0,需要自己打包進(jìn)去,在安裝時(shí)自動(dòng)檢測(cè)是否需要安裝。在 菜單 "項(xiàng)目"--"Setup屬性",在屬性窗口你會(huì)看到一個(gè)"系統(tǒng)必備",點(diǎn)擊進(jìn)入,保證“創(chuàng)建用于安裝系統(tǒng)必備組建的安裝程序”被選,“.NET Framework2.0”被選,在“指定系統(tǒng)必備組件的安裝位置”選擇 第二項(xiàng) "從與我的應(yīng)用程序相同的位置下載系統(tǒng)必備組件",確定,確定。
6、生成-〉生成Setup。
注意:為了方便程序快捷方式在用戶的'程序'菜單有規(guī)則顯示,一般要在“用戶的'程序'菜單”文件夾建立一個(gè)和你的程序相關(guān)的文件夾如,MyPrj,然后再將快捷方式和卸載菜單放進(jìn)去。
1.將.NET Framework2.0文件添也加入安裝部署項(xiàng)目
2.在"啟動(dòng)條件"里點(diǎn)".NET Framework",然后在右邊屬性的InstallUrl里填寫dotnetfx\dotnetfx.exe
3.右鍵點(diǎn)所建的安裝部署項(xiàng)目,在屬性頁的系統(tǒng)必備里選擇"從與我的應(yīng)用程序相同的位置下栽系統(tǒng)必須組件","啟動(dòng)條件"在右鍵點(diǎn)擊
文件-〉追加-〉新項(xiàng)目
右鍵點(diǎn)生成的安裝包項(xiàng)目,選擇屬性。點(diǎn)“必須的組件”,
選擇
microsoft data access components 2.8
.net framework 2.0
crystal reports for .net framework.2.0
打上勾,并且下面的3個(gè)radiobutton選中間那個(gè)(同一場(chǎng)所download)
C:\ProgramFiles\MicrosoftVisualStudio 8\SDK\v2.0\BootStrapper\Packages\CrystalReports下面的CRRedist2005_x86.msi和 CRRedist2005_x86_cn.msi(或CRRedist2005_x86_jp.msi)。
下載個(gè)dotnetfx.exe,MDAC_TYP.EXE,把這些文件都包含進(jìn)安裝盤工程。
這樣就可以做到這些效果。
【續(xù)】關(guān)于"卸載"功能的添加
上面的文章只介紹了簡(jiǎn)單的生成安裝的方法,
但是在vs.net2005下并沒有直接生成卸載程序的功能,
所以我們只好用msi來實(shí)現(xiàn)了,
原理我就不講了,網(wǎng)上一搜一堆,我只講操作,
【1】:在添加你的應(yīng)用程序項(xiàng)目的時(shí)候,多添加一個(gè)msiexec.exe進(jìn)去,
這個(gè)文件在c:\windows\system32文件夾下,
添加進(jìn)去以后,為了讓他更像個(gè)卸載程序,把他的名字改成"Uninstall.exe",
當(dāng)然這個(gè)關(guān)系不大,改不改都行的.
然后給他創(chuàng)建一個(gè)快捷方式,放到桌面或者"開始-程序"中,
我選擇放在了開始菜單中,然后下面我們要的做的就是查找這個(gè)部署項(xiàng)目的ProductCode了,
鼠標(biāo)左鍵單擊項(xiàng)目名稱,記住是左鍵單擊,然后點(diǎn)擊屬性標(biāo)簽,注意:不是右擊的屬性,
這個(gè)區(qū)別很大,這時(shí)你就可以看到ProductCode了,
然后打開你創(chuàng)建的那個(gè)快捷方式的屬性對(duì)話框,
在Aguements屬性中輸入"/x {ProductCode}",
好了,然后點(diǎn)擊"生成解決方案"即可生成帶有卸載功能的安裝程序了。
CDatabase database;
CString sDriver = "MICROSOFT EXCEL DRIVER (*.XLS)"; // Excel安裝驅(qū)動(dòng)
CString sExcelFile = "絲綢行情列表.xls"; // 要建立的Excel文件
CString sSql;
CFileDialog fileDlg(false,"XLS",sExcelFile,OFN_OVERWRITEPROMPT,"Excel文檔(*.xls)|*.xls");
fileDlg.DoModal();
sExcelFile=fileDlg.GetPathName();
TRY
{
// 創(chuàng)建進(jìn)行存取的字符串
sSql.Format("DRIVER={%s};DSN='''';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s",
sDriver, sExcelFile, sExcelFile);
// 創(chuàng)建數(shù)據(jù)庫 (既Excel表格文件)
if( database.OpenEx(sSql,CDatabase::noOdbcDialog) )
{
// 刪除表
try
{
sSql = "drop TABLE SILKLIST";
database.ExecuteSQL(sSql);
}
catch(...)
{
}
// 創(chuàng)建表結(jié)構(gòu)(姓名、年齡)
sSql = "CREATE TABLE SILKLIST (商品名稱 TEXT,交貨月 TEXT,漲幅 FLOAT,價(jià)格 FLOAT,漲跌 FLOAT,買進(jìn) FLOAT,賣出 FLOAT,凈持有量 FLOAT,購銷總量 FLOAT)";
database.ExecuteSQL(sSql);
// 插入數(shù)值
for(int i=0;i<m_data.size();i++)
{
CString per=m_data[i][2];
per.Replace("%","");
sSql.Format("INSERT INTO SILKLIST (商品名稱,交貨月,漲幅,價(jià)格,漲跌,買進(jìn),賣出,凈持有量,購銷總量) VALUES ('%s','%s',%s,%s,%s,%s,%s,%s,%s)",m_data[i][0],m_data[i][1],per,m_data[i][3],m_data[i][4],m_data[i][5],m_data[i][6],m_data[i][7],m_data[i][8]);
database.ExecuteSQL(sSql);
}
}
// 關(guān)閉數(shù)據(jù)庫
database.Close();
}
CATCH_ALL(e)
{
TRACE1("Excel驅(qū)動(dòng)沒有安裝: %s",sDriver);
}
END_CATCH_ALL;