在網絡瀏覽器軟件中,可以Internet Explorer (IE)現在是一種標準的軟件??梢钥吹?,運行不同版本的Windows操作系統(和很多其他的操作系統)的每一臺機器幾乎都使用IE。微軟已經通過ActiveX控件將IE的功能包含在執行成熟的XML處理技術中。
在本篇文章中,我們將講述如何在IE中使用ActiveX功能來訪問并解析XML文檔,由此允許網絡沖浪者操縱它們。
網上沖浪
我們以一個標準的順序文檔而開始,如表A所示。這一文檔包含簡單的順序數據以提供網絡沖浪者瀏覽之用。不僅僅為了顯示這些數據,我們還提供了一個簡單的用戶界面,網上沖浪都可以使用這一界面來瀏覽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>
我們使用一個網絡表單以訪問這一XML文檔,這一表單將顯示SKU,價格,數量,各部分的小計,以及順序中的每一選項的描述。我們的表單還包含向前和向后瀏覽選項的按鈕。
網頁的構成
網頁的重要部分是在于表單,我們將使用一個表以易讀的方式在屏幕上顯示。下面是顯示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>
請注意到,我們在表的下面包含了兩個按鈕,即通過getDataNext() 和getDataPrev()函數來瀏覽前一個和后一個的記錄,這也是我們所要討論的問題。
腳本
其實,我們網頁的實質部分不是在于表單,而是在于控制表單的腳本。在我們的腳本中包括四個部分。首先,我們通過載入XML文檔而初始化網頁。第二部分是導航到下一個記錄。第三步是導航到前一個記錄。第四部分是從XML文檔中提取單一的值。表B顯示了我們的網頁的全部內容。
表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>
運行
這一網頁將傳入并運行腳本的初始化。你一定確保order.xml文檔與jsxml.html在相同的相同的路徑上。
初始化部分將一個新的ActiveX對象例示為MSXML2.DOMDocument.3.0對象類型,然后腳本傳入order.xml文檔到內存中,并選擇所有的/Order/Item節點。我們使用/Order/Item節點以識別文檔已經包含的選項。
文檔中的<body>標準有一個onLoad屬性,這一屬性能夠使得網頁調用getDataNext()而初始化。這一功能可用于從XML文檔中獲得下一個值并顯示在表單中。我們使用一個簡單的索引來訪問特定的選項。
向前(>>)和向后(<<)按鈕都使用相同的機制。首先響應onClick事件而調用getDataNext() 或者getDataPrev(),這兩個函數使用了邏輯方法以避免文檔以外的范圍訪問我們的記錄。
最近一個項目中要用到樹形列表,本來是用mztree的,但數據用了xml,本來xml就是樹形目錄,就打算用JavaScript直接解析xml文件了,網上找到一些JavaScript操作xml的方法,在此做一個總結。
我的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>
現在我需要對這個xml文件的內容進行操作。
首先,我們需要加載這個xml文件,JavaScript中加載xml文件,是通過XMLDOM來進行的:
// 加載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文件對象出來了, 接下去我就要對這個文檔進行操作了。
比如說,我們現在需要得到節點Login/Weapon/W的第一個節點的屬性,那么我們可以如下進行:
// 首先對xml對象進行判斷
checkXMLDocObj = function(xmlFile)
{
var xmlDoc = loadXML(xmlFile);
if(xmlDoc==null)
{
alert('您的瀏覽器不支持xml文件讀取,于是本頁面禁止您的操作,推薦使用IE5.0以上可以解決此問題!');
window.location.href='/Index.aspx';
}
return xmlDoc;
}
// 然后開始獲取需要的Login/Weapon/W的第一個節點的屬性值
var xmlDoc = checkXMLDocObj('/EBS/XML/Login.xml');
var v = xmlDoc.getElementsByTagName('Login/Weapon/W')[0].childNodes.getAttribute('Text')
而我在我的程序中的寫法是這樣子的,當然我在程序中的寫法是已經應用到實際中的了.一并給出來,以供查看。
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)來進行的。
還可以通過xmlDoc.documentElement.childNodes(1)..childNodes(0).getAttribute('Text')進行訪問。
一些常用方法:
◆ xmlDoc.documentElement.childNodes(0).nodeName,可以得到這個節點的名稱;
◆ xmlDoc.documentElement.childNodes(0).nodeValue,可以得到這個節點的值. 這個值是來自于這樣子的xml格式:<a>b</b>, 于是可以得到b這個值;
◆ xmlDoc.documentElement.childNodes(0).hasChild,可以判斷是否有子節點。
根據我的經驗,最好是使用getElementsByTagName(xPath)的方法對節點進行訪問,因為這樣子可以直接通過xPath來定位節點,這樣子會有更好的性能。
//////////////////////////////////////////////////////////////////////////////////////
function print(){
fso = new ActiveXObject("Scripting.FileSystemObject");
tf = fso.CreateTextFile("E:\\test.ini", true);
tf.WriteLine("要寫入的內容");
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 //導入動態庫,裝了IE5就有
using namespace MSXML2; //引用命名空間,一般可以把命名空間理解成類和接口的集合,呵呵,對不對我也不知道了
#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); //創建XML文檔實例
}
Xml::~Xml(void)
{
CoUninitialize();
}
void Xml::AddKey(CString moduleName,CString keyName, CString keyValue)
{
CString selectString="AppSetting/"+moduleName; //XML節點定位字符串,定位到節點名為moduleName的二級節點,根節點取默認名為"AppSetting"
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMDocument,(void**)&pDoc); //創建文檔實例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("Config.xml")) //查找文件是否存在,不存在則調用函數生成一個新的XML文件
{
NewDocument(moduleName,keyName,keyValue);
return;
}
pDoc->load("Config.xml"); //從應用程序目錄中加載XML文件
MSXML2::IXMLDOMNodePtr moduleNode; //XML節點接口指針
MSXML2::IXMLDOMNodePtr keyNode; //同上
MSXML2::IXMLDOMNodePtr selectNode; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNode,(void**)&moduleNode); //創建節點實例
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); //定位到節點名為moduleName的二級節點
if(moduleNode==NULL) //如果無法定位,說明還不存在此節點,生成一個新的節點
{
selectNode=pDoc->selectSingleNode("AppSetting"); //定位到根節點,這里一定能定位成功,除非手動改了XML文件
moduleNode=pDoc->createNode(1,(_bstr_t)moduleName,""); //生成新節點
selectNode->appendChild(moduleNode); //將新節點添加到根節點
}
selectString+="/"+keyName; //XML節點定位字符串,定位到節點名為keyName的三級節點
keyNode=pDoc->selectSingleNode((_bstr_t)selectString); //定位到節點名為keyName的三級節點
if(keyNode==NULL) //如果無法定位,說明還不存在此節點,生成一個新的節點
{
keyNode=pDoc->createNode(1,(_bstr_t)keyName,""); //生成新節點
moduleNode->appendChild(keyNode); //將新節點添加到節點名moduleName的節點
}
keyNode->text=(_bstr_t)keyValue; //給節點名為keyName的節點賦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); //創建文檔實例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("Config.xml")) //查找文件是否存在,不存在則調用函數生成一個新的XML文件
{
return "";
}
pDoc->load("Config.xml");
MSXML2::IXMLDOMNodePtr selectNode; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNode,(void**)&selectNode); //創建節點實例
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); //創建文檔實例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("DataResource.xml")) //查找文件是否存在,不存在則調用函數生成一個新的XML文件
{
return false;
}
pDoc->load("DataResource.xml");
MSXML2::IXMLDOMElementPtr node; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMElement,(void**)&node); //創建節點實例
MSXML2::IXMLDOMNodeListPtr selectNodes;
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNodeList,(void**)&selectNodes);//創建節點列表實例
selectNodes=pDoc->selectNodes((_bstr_t)selectString); //查找節點集
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); //創建文檔實例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("DataResource.xml")) //查找文件是否存在,不存在則調用函數生成一個新的XML文件
{
return false;
}
pDoc->load("DataResource.xml");
MSXML2::IXMLDOMElementPtr node; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMElement,(void**)&node); //創建節點實例
MSXML2::IXMLDOMNodeListPtr tableNodes;
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNodeList,(void**)&tableNodes);//創建節點列表實例
MSXML2::IXMLDOMNodeListPtr fieldNodes;
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMNodeList,(void**)&fieldNodes);//創建節點列表實例
tableNodes=pDoc->selectNodes((_bstr_t)selectString); //查找節點集
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); //創建文檔實例
CFileFind finder; //查找文件是否存在的MFC類
if(!finder.FindFile("DataResource.xml")) //查找文件是否存在,不存在則調用函數生成一個新的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); //創建節點實例
MSXML2::IXMLDOMElementPtr tableNode; //同上
hr=CoCreateInstance(MSXML2::CLSID_DOMDocument,NULL,CLSCTX_ALL,MSXML2::IID_IXMLDOMElement,(void**)&tableNode); //創建節點實例
tablesNode=pDoc->selectSingleNode((_bstr_t)selectString); //查找節點集
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); //創建節點列表實例
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); //創建節點實例
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); //創建節點實例
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.徹底關閉Excel進程
rang.ReleaseDispath();
sheet.ReleaseDispath();
sheets.ReleaseDispath();
book.ReleaseDispath();
books.ReleaseDispath();
ExcelApp.Quit();//ExcelApp,是_Applacation對象,以上幾個對象同理。
ExcelApp.ReleaseDispath();
注意:最后兩行代碼順序不要反了,否則不能徹底關閉Excel進程,這是關鍵
2.將Excel文件保存為HTML網頁
sheet.SaveAs(strFileName,ColeVariant((long)44),vtMissing,...后面參數全是vtMissing);
sheet.SaveAs(strFileName,vtMissing,vtMissing,...后面參數全是vtMissing);
3.不顯示任何警告對話框
在保存文件代碼之前加上下面語句
ExcelApp.SetAlertBeforeOverwritting(false);
ExcelApp.SetDisplayAlert(false);
在開發軟件時,經常要將數據輸出到Excel 2000中,在Excel 2000中對該數據進行進一步地格式化處理或進行計算處理。在Visual Basic中處理起來較簡單,Excel 2000的VB編程幫助中有較為詳細的介紹。在Visual C++中如何進行處理了?利用Excel 2000的ActiveX Automate功能,處理起來同VB中類似。但要注意以下幾點:
對于對象的屬性值的讀取或賦值,需要用GetProperty()或SetProperty(NewValue)函數,不能象VB中直接通過屬性名稱取值或賦值。例如:Worksheet.GetCount(), Worksheet.SetName(“Sheet1”)。 |
對集合對象中的成員對象的引用,必須使用集合對象的GetItem()函數。例如:Worksheets.GetItem(ColeVariant((long)1))或Worksheets.GetItem(ColeVariant(“Sheet1”))取得第一個工作表。 |
在COM接口中,時常用到Variant,BSTR,SafeArray數據類型。Variant數據類型是一個聯合,可表示幾乎所有的類型的數據,具體用法見MSDN中的相關介紹,類_variant_t是對VARIANT數據類型的封裝。在Excel 2000的VB編程幫助中,如果提到某函數或屬性需要一個值,該值的數據類型通常是Variant,在封裝Excel 2000對象的類定義中,說明了具體需要的數據類型。BSTR是一個包括了字符串和字符串長度的數據結構,類_bstr_t是對BSTR數據類型的封裝。在Excel 2000的VB編程幫助中提到的字符串通常指BSTR。具體函數參數或屬性的數據類型,見封裝該對象的類的定義。SafeArray是一個包括數組和數組邊界的結構,數組邊界外的內容不允許訪問。在Excel 2000的VB編程幫助中提到的數組是指SafeArray。關于SafeArray的處理,請見MSDN的相關幫助。 |
對于缺省參數和缺省值。在VB中,函數的參數可以空缺,在VC++中不允許,必須將所有的參數填寫完全。如果你希望指定某個參數為缺省值,根據參數數據類型的不同,可指定不同的缺省值。當參數數據類型為字符串時,可以用長度為0的字符串。如果參數是Variant類型,可用常量vtMissing,該常量在comdef.h中定義。也可用_variant_t(DISP_E_PARAMNOTFOUND, VT_ERROR)產生一個Variant對象。 |
Excel對象中的集合對象有時包括的子對象是不一定的,例如:Range對象,可以表示Cell的集合,也可以表示Column的集合或Row的集合,Range.GetItem(1)可以返回Cell或Column或Row對象。 |
對對象的引用或傳遞對象,使用IDispatch類對象,有時利用Variant對IDispatch進行包裝。 |
以下是一段源程序,演示如何啟動Excel 2000,利用一個模板文件產生一個新文檔,在該文檔的”Sheet1”工作表的第一個單元中填寫一段文字,設置第一列的列寬,然后調用一個模板中的宏,執行一段程序,最后打印預覽該Excel文檔。模板文件名稱:MyTemplate.xlt。程序在Visual C++ 6.0 sp4,Windows 2000 Professional sp-1下調試通過。 |
首先利用Visual C++ 6.0,建立一個MFC基于對話框的工程項目,共享DLL,Win32平臺。工程名稱ExcelTest。在主對話框中加入一個按鈕, |
雙擊該按鈕,增加成員函數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\是本機上Microsoft Office 2000的安裝目錄,可根據個人機器上的實際安裝目錄修改)。選擇_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range,加入新類,分別為_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range,頭文件Excel9.h,源文件Excel9.cpp。 |
在ExcelTestDlg.cpp文件的頭部,#include "ExcelTestDlg.h"語句之下,增加 : |
在void CExcelTestDlg::OnExceltest() 函數中增加如下代碼: |
void CExcelTestDlg::OnExceltest() |
//創建Excel 2000服務器(啟動Excel) |
if (!ExcelApp.CreateDispatch("Excel.Application",NULL)) |
AfxMessageBox("創建Excel服務失敗!"); |
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,此時,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(); |
如何自動執行將 Excel 工作表保存為 HTML 文件中使用 Visual c + +
http://support.microsoft.com/kb/199691/zh-cn
VC操作Excel,當用SaveAs保存Excel時,如果待保存路徑下已經存在該Excel,則會彈出一個對話框提示你當前路徑下已經存在該Excel,是否替換,下面有三個按鈕:“是”、“否”、“取消”。如果選擇了“取消”則會彈出一個錯誤警告對話框。
可以按照如下方法解決這個問題:在SaveAs之前添加代碼: _Application ExcelApp; ExcelApp.SetAlertBeforeOverwriting(FALSE); ExcelApp.SetDisplayAlerts(FALSE);
在Office2003版Office所生成的Excel.cpp文件中,類_Workbook的SaveAs函數,其函數原型如下: 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);
參數含義參考如下: 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
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
本人參考網上做法,利用模板實現了VC對EXCEL的操作,但是存在以下問題:
1.第一次運行程序,點擊保存時沒問題,當第二次運行程序時,會彈出對話框,提示已經存在文件,是否替換(是、否、取消),當點擊“否”的時候會彈出警告對話框,程序中斷;
2.程序運行后,第一次點擊保存時,不會出錯,接著再次點擊保存時,就會出現警告:無法找到模板......;即程序運行后不能實現多次保存。
3.程序在關閉后,為何在任務管理器的進程里并沒有結束,即不能實現程序在后臺也關閉。
以下是源代碼,有勞哪位大俠解惑!不勝感激!
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("創建Excel服務失??!", "信息提示", 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("寫入數據了"));
range.SetItem(_variant_t((long)2), _variant_t((long)3), _variant_t("寫入數據了"));
range.SetItem(_variant_t((long)3), _variant_t((long)3), _variant_t("寫入數據了"));
range.SetItem(_variant_t((long)4), _variant_t((long)3), _variant_t("寫入數據了"));
if(IDOK==fileDlg.DoModal())//這里實現“另存為”對話框
{
Path=fileDlg.GetPathName();
Name=fileDlg.GetFileName();
//保存數據
_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();
}
以上幾個問題已經解決,倒騰了一晚上。
(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);
這樣的話問題就解決了。
今天終于安裝了一個Visual Studio 2005 Team Suite簡體中文版,新建立了個工程感覺速度比2003快很多,而且界面設置功能也強大了很多,內置XP風格菜單和工具條。打包時可以自動檢測.NET Framework 2.0并將其集成到安裝包,而不像2003需要安裝引導程序插件PluginInstaller.msi才能做到這一點。
就是不知道目前的GIS開發工具能不能用在2005的開發環境中。
如果已經完成了項目的開發就需要進行打包分發。下面將2005下的打包分發進行簡單介紹
開發過程和2003雷同,主要介紹打包過程。(以VisualBasic為例,項目名稱為MyPrj)
1、在開發完成的項目工程MyPrj中,文件-〉添加-〉新建項目,在添加新項目對話框中選擇其他項目類型-安裝和部署,在模板中選擇安裝項目并取名SetupMyPrj
2、解決方案資源管理器中選擇SetupMyPrj雙擊,從文件系統(SetupMyPrj)中的“目標計算機上的文件系統”選擇"應用程序文件夾"單擊右鍵,添加“項目輸出”,選擇主輸出,確定后即產生“主輸出來自MyPrj(活動)”的字樣,同時具有相關的依賴項文件。
3、按照需求添加用戶的程序菜單和用戶桌面快捷方式。
在“主輸出來自MyPrj(活動)”單擊右鍵,選擇“創建 主輸出來自MyPrj(活動) 的快捷方式”,創建后,重命名為“MyPrj”,然后拖動到“用戶桌面”的文件夾下。這樣的話,安裝后,在用戶桌面上就存在應用程序的快捷方式了。此處可以同過快捷方式的屬性來制定快捷方式的圖標。
創建 “用戶的'程序'菜單”快捷方式,再重復上面的操作即可。將創建的快捷方式拖到“用戶的'程序'菜單”文件夾下。
4、一般開發軟件都要有軟件的卸載功能,這個可通過Windows的msiexec.exe實現。選擇SetupMyPrj,右鍵,選擇“添加文件”,瀏覽到系統安裝盤下的msiexec.exe,(一般路徑為 c:\windows\system32\msiexec.exe),添加到你的方案里面,此刻該程序會在"應用程序文件夾"出現,右鍵,選擇“創建msiexec.exe快捷方式”,命名為“卸載MyPrj”,然后拖到“用戶的'程序'菜單”即可。最后要在該快捷方式的Arguments 屬性里面寫入“/x {ProductID}”,ProductID是你創建的項目的Product Code,主要不要有引號。此時,卸載功能完成,當然你也可以為卸載菜單指定一個個性圖標。
5、為了避免目標計算機沒有程序運行需求的.net framework2.0,需要自己打包進去,在安裝時自動檢測是否需要安裝。在 菜單 "項目"--"Setup屬性",在屬性窗口你會看到一個"系統必備",點擊進入,保證“創建用于安裝系統必備組建的安裝程序”被選,“.NET Framework2.0”被選,在“指定系統必備組件的安裝位置”選擇 第二項 "從與我的應用程序相同的位置下載系統必備組件",確定,確定。
6、生成-〉生成Setup。
注意:為了方便程序快捷方式在用戶的'程序'菜單有規則顯示,一般要在“用戶的'程序'菜單”文件夾建立一個和你的程序相關的文件夾如,MyPrj,然后再將快捷方式和卸載菜單放進去。
1.將.NET Framework2.0文件添也加入安裝部署項目
2.在"啟動條件"里點".NET Framework",然后在右邊屬性的InstallUrl里填寫dotnetfx\dotnetfx.exe
3.右鍵點所建的安裝部署項目,在屬性頁的系統必備里選擇"從與我的應用程序相同的位置下栽系統必須組件","啟動條件"在右鍵點擊
文件-〉追加-〉新項目
右鍵點生成的安裝包項目,選擇屬性。點“必須的組件”,
選擇
microsoft data access components 2.8
.net framework 2.0
crystal reports for .net framework.2.0
打上勾,并且下面的3個radiobutton選中間那個(同一場所download)
C:\ProgramFiles\MicrosoftVisualStudio 8\SDK\v2.0\BootStrapper\Packages\CrystalReports下面的CRRedist2005_x86.msi和 CRRedist2005_x86_cn.msi(或CRRedist2005_x86_jp.msi)。
下載個dotnetfx.exe,MDAC_TYP.EXE,把這些文件都包含進安裝盤工程。
這樣就可以做到這些效果。
【續】關于"卸載"功能的添加
上面的文章只介紹了簡單的生成安裝的方法,
但是在vs.net2005下并沒有直接生成卸載程序的功能,
所以我們只好用msi來實現了,
原理我就不講了,網上一搜一堆,我只講操作,
【1】:在添加你的應用程序項目的時候,多添加一個msiexec.exe進去,
這個文件在c:\windows\system32文件夾下,
添加進去以后,為了讓他更像個卸載程序,把他的名字改成"Uninstall.exe",
當然這個關系不大,改不改都行的.
然后給他創建一個快捷方式,放到桌面或者"開始-程序"中,
我選擇放在了開始菜單中,然后下面我們要的做的就是查找這個部署項目的ProductCode了,
鼠標左鍵單擊項目名稱,記住是左鍵單擊,然后點擊屬性標簽,注意:不是右擊的屬性,
這個區別很大,這時你就可以看到ProductCode了,
然后打開你創建的那個快捷方式的屬性對話框,
在Aguements屬性中輸入"/x {ProductCode}",
好了,然后點擊"生成解決方案"即可生成帶有卸載功能的安裝程序了。
CDatabase database;
CString sDriver = "MICROSOFT EXCEL DRIVER (*.XLS)"; // Excel安裝驅動
CString sExcelFile = "絲綢行情列表.xls"; // 要建立的Excel文件
CString sSql;
CFileDialog fileDlg(false,"XLS",sExcelFile,OFN_OVERWRITEPROMPT,"Excel文檔(*.xls)|*.xls");
fileDlg.DoModal();
sExcelFile=fileDlg.GetPathName();
TRY
{
// 創建進行存取的字符串
sSql.Format("DRIVER={%s};DSN='''';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s",
sDriver, sExcelFile, sExcelFile);
// 創建數據庫 (既Excel表格文件)
if( database.OpenEx(sSql,CDatabase::noOdbcDialog) )
{
// 刪除表
try
{
sSql = "drop TABLE SILKLIST";
database.ExecuteSQL(sSql);
}
catch(...)
{
}
// 創建表結構(姓名、年齡)
sSql = "CREATE TABLE SILKLIST (商品名稱 TEXT,交貨月 TEXT,漲幅 FLOAT,價格 FLOAT,漲跌 FLOAT,買進 FLOAT,賣出 FLOAT,凈持有量 FLOAT,購銷總量 FLOAT)";
database.ExecuteSQL(sSql);
// 插入數值
for(int i=0;i<m_data.size();i++)
{
CString per=m_data[i][2];
per.Replace("%","");
sSql.Format("INSERT INTO SILKLIST (商品名稱,交貨月,漲幅,價格,漲跌,買進,賣出,凈持有量,購銷總量) 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);
}
}
// 關閉數據庫
database.Close();
}
CATCH_ALL(e)
{
TRACE1("Excel驅動沒有安裝: %s",sDriver);
}
END_CATCH_ALL;