运行环境:WIN7 X64 + iis6.1
开发环境:vs2012+SQL2005
服务器环境:2003 X64 + SQL2005 + IIS 6.0
需求: 企业中需要各种各样的报表诸如WORD,简单还好说,稍微比较复杂点的,需要根据录入的信息去生成特定格式的WORD.大概15页左右包含[基本信息][业务情况][联系人信息][店面图片][记录描述][财务指标数据][评分卡][信用评级][反馈信息]等;有些内容不固定诸如[记录描述]中有可能有没有记录,有可能是1-5条数据 也有可能是超过10条的数据.还有要支持图片的插入,WORD排版等因素.
方案:根本业务部门给出的WORD样本制作WORD文档模板(即xxx.dot文件)设置[书签],然后用应用程序调用本地WORD的COM对象接口,查找[书签]填充数据;
排版问题:文档模板可以适用模板随时可以调整,删减内容还要删减对应的[书签]否则会有[书签]找不到的问题.
图片插入:[书签]支持图片插入;
不固定的记录:我分为二种情况.1.动态数据量小的3条以内,那么我就以最大为主在WORD中占位3条数据. 2.数据量大的咨询业务部门实际数目设置最大数,然后用书签占位,相当与把动态数据都搞成固定数.都是基于实际工作量战线拉太长于实际实现不利.(有兴趣的朋友可以去研究下[动态占位]问题,需要解决掉,因为模板设置,占位都需要参考业务部门给出样本WORD来对比手工占位,系统占位就要考虑换行,空格等问题.)
其他:[书签]使用方法,根据样本WORD,打开WORD另存为.dot格式,鼠标点击需要插入[书签]的位置,点击菜单栏[插入]-[书签],键入书签名即可.
查找[书签],Ctrl+F 查找选择[定位]选项卡 定位目标[书签]
代码实现思路:
1.整理需要填充到WORD模板中的数据
2.调用CCWordApp查找模板.dot 根据[书签]去填充(文本,数字,图片)
3.保存WORD(id标识+日期 防止文件重复.)然后供用户下载.(扩展,可以安装WORD转PDF组件 在服务端就可以找到生成后的WORD转换PDF供用户下载,满足一部分文件安全性要求比较高,不允许用户修改.)
具体代码如下:
业务代码
using Microsoft.Office.Interop.Word;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.UI.WebControls;
public partial class CustInfoManage_PrintPage : System.Web.UI.Page
{
object missing = System.Reflection.Missing.Value;
object readOnly = false;
object isVisible = true;
private CCWordApp test;
DAL Da = new DAL();
///
/// 使用模板
///
public void OpenModelWordSave(object sender, EventArgs e)
{
//根据 客户编码 获取并组织WORD文档所需的所有信息.
string CustCode = ShowCustLabel.Text;
if (CustCode == "")
{
return;
}
#region 填充信息整理 此处省略
//String gsmc = Dr1["SaleComp"].ToString();//公司名称
#endregion
try
{
test = new CCWordApp();
test.Open(System.Configuration.ConfigurationManager.AppSettings["WordMod"] + "template1.dot");
#region 查找书签并替换
test.GotoBookMark("gsmc");
test.InsertText(gsmc);
test.SetFont("nothing");
test.GotoBookMark("dmcqxz_C");
test.InsertText(dmcqxz_C);
test.SetFont("nothing");
if (!String.IsNullOrWhiteSpace(dmtp1_C))
{
test.GotoBookMark("dmtp1_C");
test.InsertPicture(System.Configuration.ConfigurationManager.AppSettings["OtherImage"] + dmtp1_C);
test.SetFont("nothing");
}
if (!String.IsNullOrWhiteSpace(dmtp2_C))
{
test.GotoBookMark("dmtp2_C");
test.InsertPicture(System.Configuration.ConfigurationManager.AppSettings["OtherImage"] + dmtp2_C);
test.SetFont("nothing");
}
if (!String.IsNullOrWhiteSpace(cktp1_C))
{
test.GotoBookMark("cktp1_C");
test.InsertPicture(System.Configuration.ConfigurationManager.AppSettings["OtherImage"] + cktp1_C);
test.SetFont("nothing");
}
if (!String.IsNullOrWhiteSpace(cktp2_C))
{
test.GotoBookMark("cktp2_C");
test.InsertPicture(System.Configuration.ConfigurationManager.AppSettings["OtherImage"] + cktp2_C);
test.SetFont("nothing");
}
test.GotoBookMark("dyfxjhyhck_D");
test.InsertText(dyfxjhyhck_D);
test.SetFont("nothing");
#endregion
string createTime = DateTime.Now.ToString("yyyyMMddHHmmss");
string fileName = CustCode + "_" + createTime + ".doc";
test.SaveAs(System.Configuration.ConfigurationManager.AppSettings["WordDoc"] + fileName);
test.Quit();
#region 保存到数据库
string InsertCommand = "INSERT INTO [CRM_CB_DownFileWord] "
+ "( [CustCode],[fileName], [createTime])"
+ " VALUES "
+ "(@CustCode,@fileName, @createTime)";
SqlCommand SqlCmd = new SqlCommand(InsertCommand);
SqlCmd.Parameters.Add("@CustCode", System.Data.SqlDbType.Decimal).Value = CustCode;
SqlCmd.Parameters.Add("@fileName", System.Data.SqlDbType.NVarChar).Value = fileName;
SqlCmd.Parameters.Add("@createTime", System.Data.SqlDbType.NVarChar).Value = createTime;
string Mess = "";
if (Da.ExecuteNonQuery(SqlCmd))
{
Mess = CustCode + " 保存成功!";
BaseCls.Alert(Page, Mess);
}
else
{
BaseCls.Alert(Page, "错误,请检查!");
return;
}
#endregion
}
catch (Exception exc)
{
test.Quit();
throw (exc);
}
}
}
CCWordApp实体类:
using System;
using System.ComponentModel;
public class CCWordApp
{
private Microsoft.Office.Interop.Word.ApplicationClass oWordApplic; // a reference to Word application 引用Word应用程序
private Microsoft.Office.Interop.Word.Document oDoc; // a reference to the document 引用文档
public CCWordApp()
{
// activate the interface with the COM object of Microsoft Word
//激活与Microsoft Word的COM对象的接口
oWordApplic = new Microsoft.Office.Interop.Word.ApplicationClass();
}
///
/// 插入图片
///
///
public void InsertPicture(string picPath)
{
object missing = System.Reflection.Missing.Value;
oWordApplic.Selection.InlineShapes.AddPicture(picPath, ref missing, ref missing, ref missing);
}
// Open a file (the file must exists) and activate it 打开一个文件(该文件必须存在),并激活它
public void Open(string strFileName)
{
object fileName = strFileName;
object readOnly = false;
object isVisible = true;
object missing = System.Reflection.Missing.Value;
oDoc = oWordApplic.Documents.Open(ref fileName, ref missing, ref readOnly,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref isVisible, ref missing, ref missing, ref missing);
oDoc.Activate();
}
// Open a new document打开一个新文档
public void Open()
{
object missing = System.Reflection.Missing.Value;
oDoc = oWordApplic.Documents.Add(ref missing, ref missing, ref missing, ref missing);
oDoc.Activate();
}
public void Quit()
{
object missing = System.Reflection.Missing.Value;
oWordApplic.Application.Quit(ref missing, ref missing, ref missing);
}
public void Save()
{
oDoc.Save();
}
public void SaveAs(string strFileName)
{
object missing = System.Reflection.Missing.Value;
object fileName = strFileName;
oDoc.SaveAs(ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
}
// Save the document in HTML format 以HTML格式保存文档
public void SaveAsHtml(string strFileName)
{
object missing = System.Reflection.Missing.Value;
object fileName = strFileName;
object Format = (int)Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatHTML;
oDoc.SaveAs(ref fileName, ref Format, ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
}
public void InsertText(string strText)
{
oWordApplic.Selection.TypeText(strText);
}
public void InsertLineBreak()
{
oWordApplic.Selection.TypeParagraph();
}
public void InsertLineBreak(int nline)
{
for (int i = 0; i < nline; i++)
oWordApplic.Selection.TypeParagraph();
}
// Change the paragraph alignement 更改段落对齐键相
public void SetAlignment(string strType)
{
switch (strType)
{
case "Center":
oWordApplic.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter;
break;
case "Left":
oWordApplic.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphLeft;
break;
case "Right":
oWordApplic.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphRight;
break;
case "Justify":
oWordApplic.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphJustify;
break;
}
}
// if you use thif function to change the font you should call it again with 如果您使用此功能来改变字体,你应该再次调用它
// no parameter in order to set the font without a particular format 为了不带参数设置字体没有特定的格式
public void SetFont(string strType)
{
switch (strType)
{
case "Bold":
oWordApplic.Selection.Font.Bold = 1;
break;
case "Italic":
oWordApplic.Selection.Font.Italic = 1;
break;
case "Underlined":
oWordApplic.Selection.Font.Subscript = 0;
break;
}
}
// disable all the style 禁用所有的风格
public void SetFont()
{
oWordApplic.Selection.Font.Bold = 0;
oWordApplic.Selection.Font.Italic = 0;
oWordApplic.Selection.Font.Subscript = 0;
}
public void SetFontName(string strType)
{
oWordApplic.Selection.Font.Name = strType;
}
public void SetFontSize(int nSize)
{
oWordApplic.Selection.Font.Size = nSize;
}
public void InsertPagebreak()
{
// VB : Selection.InsertBreak Type:=wdPageBreak
object pBreak = (int)Microsoft.Office.Interop.Word.WdBreakType.wdPageBreak;
oWordApplic.Selection.InsertBreak(ref pBreak);
}
// Go to a predefined bookmark, if the bookmark doesn't exists the application will raise an error
//去到一个预先定义的书签,如果书签不存在应用程序将引发错误
public void GotoBookMark(string strBookMarkName)
{
// VB : Selection.GoTo What:=wdGoToBookmark, Name:="nome"
object missing = System.Reflection.Missing.Value;
object Bookmark = (int)Microsoft.Office.Interop.Word.WdGoToItem.wdGoToBookmark;
object NameBookMark = strBookMarkName;
oWordApplic.Selection.GoTo(ref Bookmark, ref missing, ref missing, ref NameBookMark);
}
public void GoToTheEnd()
{
// VB : Selection.EndKey Unit:=wdStory
object missing = System.Reflection.Missing.Value;
object unit;
unit = Microsoft.Office.Interop.Word.WdUnits.wdStory;
oWordApplic.Selection.EndKey(ref unit, ref missing);
}
public void GoToTheBeginning()
{
// VB : Selection.HomeKey Unit:=wdStory
object missing = System.Reflection.Missing.Value;
object unit;
unit = Microsoft.Office.Interop.Word.WdUnits.wdStory;
oWordApplic.Selection.HomeKey(ref unit, ref missing);
}
public void GoToTheTable(int ntable)
{
// Selection.GoTo What:=wdGoToTable, Which:=wdGoToFirst, Count:=1, Name:=""
// Selection.Find.ClearFormatting
// With Selection.Find
// .Text = ""
// .Replacement.Text = ""
// .Forward = True
// .Wrap = wdFindContinue
// .Format = False
// .MatchCase = False
// .MatchWholeWord = False
// .MatchWildcards = False
// .MatchSoundsLike = False
// .MatchAllWordForms = False
// End With
object missing = System.Reflection.Missing.Value;
object what;
what = Microsoft.Office.Interop.Word.WdUnits.wdTable;
object which;
which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToFirst;
object count;
count = 1;
oWordApplic.Selection.GoTo(ref what, ref which, ref count, ref missing);
oWordApplic.Selection.Find.ClearFormatting();
oWordApplic.Selection.Text = "";
}
public void GoToRightCell()
{
// Selection.MoveRight Unit:=wdCell
object missing = System.Reflection.Missing.Value;
object direction;
direction = Microsoft.Office.Interop.Word.WdUnits.wdCell;
oWordApplic.Selection.MoveRight(ref direction, ref missing, ref missing);
}
public void GoToLeftCell()
{
// Selection.MoveRight Unit:=wdCell
object missing = System.Reflection.Missing.Value;
object direction;
direction = Microsoft.Office.Interop.Word.WdUnits.wdCell;
oWordApplic.Selection.MoveLeft(ref direction, ref missing, ref missing);
}
public void GoToDownCell()
{
// Selection.MoveRight Unit:=wdCell
object missing = System.Reflection.Missing.Value;
object direction;
direction = Microsoft.Office.Interop.Word.WdUnits.wdLine;
oWordApplic.Selection.MoveDown(ref direction, ref missing, ref missing);
}
public void GoToUpCell()
{
// Selection.MoveRight Unit:=wdCell
object missing = System.Reflection.Missing.Value;
object direction;
direction = Microsoft.Office.Interop.Word.WdUnits.wdLine;
oWordApplic.Selection.MoveUp(ref direction, ref missing, ref missing);
}
// this function doesn't work 这个功能不起作用
public void InsertPageNumber(string strType, bool bHeader)
{
object missing = System.Reflection.Missing.Value;
object alignment;
object bFirstPage = false;
object bF = true;
//if (bHeader == true)
//WordApplic.Selection.HeaderFooter.PageNumbers.ShowFirstPageNumber = bF;
switch (strType)
{
case "Center":
alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberCenter;
//WordApplic.Selection.HeaderFooter.PageNumbers.Add(ref alignment,ref bFirstPage);
//Word.Selection objSelection = WordApplic.pSelection;
//oWordApplic.Selection.HeaderFooter.PageNumbers.Item(1).Alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberCenter;
break;
case "Right":
alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberRight;
//oWordApplic.Selection.HeaderFooter.PageNumbers.Item(1).Alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberRight;
break;
case "Left":
alignment = Microsoft.Office.Interop.Word.WdPageNumberAlignment.wdAlignPageNumberLeft;
oWordApplic.Selection.HeaderFooter.PageNumbers.Add(ref alignment, ref bFirstPage);
break;
}
}
}
//object units = WdUnits.wdCharacter;
//object last=doc.Characters.Count;
//doc.Range(ref first, ref last).Delete(ref units, ref last)
发布测试环境可能会遇到的问题1:
行 1679: catch (Exception exc)
行 1680: {
行 1681: throw (exc);
行 1682: //StatusMessage.Text = exc.Message;
行 1683: //StatusMessage.Visible = true; |
[UnauthorizedAccessException: 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问。 (异常来自 HRESULT:0x80070005 (E_ACCESSDENIED))。] CustInfoManage_PrintPage.OpenModelWordSave(Object sender, EventArgs e) in e:\T1Web - 测试\CustInfoManage\PrintPage.aspx.cs:1681 System.Web.UI.WebControls.Button.OnClick(EventArgs e) +9556538 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +103 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1724 |
解决方案:
参考此文链接:http://axislover.blog.163.com/blog/static/10776515200832531059319/
如果无法访问摘录如下:
Application当程序运行到这句时出现下面的错误:检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005。3.单击"安全"选项卡,分别在"启动和激活权限"和"访问权限"组中选中"自定义",然后 自定义->编辑->添加ASP.NET账户和IUSER_计算机名。解决方法二:如果上述方法不能解决问题,就应该是权限问题,请尝试用下面 的方法:在web.config中使用身份模拟,在
1:在服务器上安装office的word软件.
2:在"开始"- >"运行"中输入dcomcnfg.exe启动"组件服务"
3:依次双击"组件服务"- >"计算机"- >"我的电脑"- >"DCOM配置"
4:在"DCOM配置"中找到"Microsoft word应用程序",在它上面点击右键,然后点击"属性",弹出"Microsoft word应用程序属性"对话框
5:点击"标识"标签,选择"交互式用户"
6:点击"安全"标签,在"启动和激活权限"上点击"自定义",然后点击对应的"编辑"按钮,在弹出的"安全性"对话框中填加
一个"NETWORK SERVICE"用户(注意要选择本计算机名),并给它赋予"本地启动"和"本地激活"权限.
7:依然是"安全"标签,在"访问权限"上点击"自定义",然后点击"编辑",在弹出的"安全性"对话框中也填加一个"NETWORK
SERVICE"用户,然后赋予"本地访问"权限.
这样,我们便配置好了相应的word的DCOM权限.
注意:这是在WIN2003上配置的,在2000上,可能是配置ASPNET用户
由于word是在服务器上打开的,所以应该写一个把导出数据保存在服务器上,然后再传递给客户端的方法,最后每次调用这个功能的时候再删除以前在服务器上所生成的所有word
检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005
在CSDN上总是有网友问这个问题,自己也遇到过,因些写出来供参考:
症状:
oWordApplic = New Word.Application
当程序运行到这句时出现下面的错误:
检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005。
oWordApplic = New Word.Application
当程序运行到这句时出现下面的错误:
检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005。
解决方法一:
控制面板-》管理工具-》组件服务-》计算机-》我的电脑-》DCom配置-》找到Microsoft Word文档
之后
单击属性打开此应用程序的属性对话框。
2. 单击标识选项卡,然后选择交互式用户。
3.单击"安全"选项卡,分别在"启动和激活权限"和"访问权限"组中选中"自定义",然后
自定义->编辑->添加ASP.NET账户和IUSER_计算机名
* 这些帐户仅在计算机上安装有 IIS 的情况下才存在。
13. 确保允许每个用户访问,然后单击确定。
14. 单击确定关闭 DCOMCNFG。
解决方法二:
如果上述方法不能解决问题,就应该是权限问题,请尝试用下面的方法:
在web.config中使用身份模拟,在
PS:进我自己测试,做完1-7步骤就已经可以修复这个问题了.
发布测试环境可能会遇到的问题2:
明明有装Word2007, 并且程序也能用这个组件来操作Word, 可为什么组件服务里面看不到CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件?我是希望能显示CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件, 好设置它的权限了。 省得ASP.NET要模拟帐户
在64bit系统中的DCOM管理中添加32Bit的Excel、Word等的管理)
1).开始--〉运行--〉cmd
2)命令提示符下面,输入“mmc -32”回车,打开32的控制台
3).文件菜单中,添加删除管理单元--〉“组件服务”(在最下面),确认后,关闭即可。
4).开始-管理工具-组件服务,在"DCOM配置"中,可以找到“"Microsoft Excel 应用程序”了。找到“Microsoft Excel 应用程序”,在它上面点击右键,然后点击"属性",弹出"Microsoft Excel 应用程序属性"对话框 5).点击“标识”标签,选择“交互式用户” **:这个在32Bit的2003上或XP上不需要,但这里需要。 6).点击"安全"标签,在"启动和激活权限"上点击"自定义",然后点击对应的"编辑"按钮,在弹出的"安全性"对话框中填加一个"NETWORK SERVICE"用户(注意要选择本计算机名),并给它赋予"本地启动"和"本地激活"权限
7).依然是"安全"标签,在"访问权限"上点击"自定义",然后点击"编辑",在弹出的"安全性"对话框中也填加一个"NETWORK SERVICE"用户,然后赋予"本地访问"权限.
PS:这个问题算是误导了.我是先碰到问题2的,但是按此方法无法解决,用问题1中在"开始"- >"运行"中输入dcomcnfg.exe启动"组件服务"即可查到WORD组件.
发布测试环境可能会遇到的问题3:
执行当前 Web 请求期间生成了未经处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。 |
[HttpException (0x80004005): 当前标识(IT-CHENXIAOPENG\test)没有对“C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files”的写访问权限。] System.Web.HttpRuntime.SetUpCodegenDirectory(CompilationSection compilationSection) +9902226 System.Web.HttpRuntime.HostingInit(HostingEnvironmentFlags hostingFlags, PolicyLevel policyLevel, Exception appDomainCreationException) +199 [HttpException (0x80004005): 当前标识(IT-CHENXIAOPENG\test)没有对“C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files”的写访问权限。] System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9880168 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +101 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +254 |
版本信息: Microsoft .NET Framework 版本:4.0.30319; ASP.NET 版本:4.0.30319.18067
PS:这个问题是我自己搞出来的.还记得问题1中我们配置了web.config中设置了一个用TEST(
其实这里有个问题,上面将test用户从管理员用户组变更为普通用户组,网站调用正常.更改用户组 还有一点是:[直到下一次用户登录时对用户组成员关系的更改才生效].
所以我上面PS中说的才能成功.隔天后我才暴露出了这个问题. 新建了一个管理组用户test2才对比出了这个问题.希望引以为鉴.