在网络浏览器软件中,可以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;