`
bcyy
  • 浏览: 1825397 次
文章分类
社区版块
存档分类
最新评论

如何在Word中实现Excel图表刷新

 
阅读更多

在word2003的时代,word中图表的实现,还是通过MSChart(如图1)来实现的,该图表控件在word中是OLE COM对象,是以out-process的方式进行工作。在VSTO中可以对其进行直接操作。但MSChart的图表对象确实在样式和美观上远不及word2007之后的excel图表。如图2,MSChart图表的样式。

figure 1. 添加MSChart对象

figure 2. MSChart图表样式

当然要是word2007中的图表,就必须要求office的版本在2007或更高。但是安装了office2007后,使用VS2008创建word2007插件,貌似还不能实现excel图表的操作,无论怎么找也找不到Chart相关的接口。 原来PIA 2007中Microsoft.Office.Interop.Word.dll好像没有这部分接口(如图3)。是否通过VSTO就无法操作excel图表来吗?默认在VS2008中新建的WORD2007插件项目中,引用的Microsoft.Office.Interop.Word.dll是微软官方PIA提供的dll文件,如图4.

figure 3.PIA 2007 中Microsoft.Office.Interop.Word.dll部分接口

figure 4.默认引用pia的dll文件

PIA是Primary Interop Assemblies的简称,它是由微软提供的接口组件,其中包含了COM接口的类型定义,方法签名等。它是.net操作COM的一种实现方式--—COM Interop。而PIA是微软官方提供了一套操作WORD的COM接口,只是貌似漏了一些接口而已。无论是官方还是非官方提供的接口,要想实现COM接口,客户机必须依据注册了该COM对象,否则也无法使用。一般只有客户机安装了office,那么就已经注册了Office的相关COM对象,如Excel,Word等。我们可以通过引用COM的方式,来让VS2008帮我们生成COM的接口签名,如图添加Microsoft Word 14.0 Object Library,由于本机安装的是office2010,因此就没有Microsoft Word 12.0 Object Library。

figure 5. 添加Microsoft Word 14.0 Object Library COM 引用
添加完COM引用后,在项目的引用列表中出现了Microsoft.Office.Interop.Word.dll和默认的PIA引用名称是一样的,但属性却有很大不同。如图6

figure 6.Microsoft Word 14.0 Object Library COM 引用的属性

这是因为VS2008生成的Interop是放在GAC中的,并且版本号也与PIA有很大不同。最重要的是,该dll中包含了Chart相关接口。如图7.

figure 7. Microsoft Word 14.0 Object Library接口

有了这些接口,操作Excel图表就没有问题了,因为由于操作的是excel图表,图表的数据是存储在excel中的,因此也需要将excel的com或PIA引用进WORD插件项目中,这样就可以方便的操作excel中的数据了。另外如果您觉得引用COM不方便,或者没有安装office2007而安装的是office2010的话,您可以自己编写Interop,并指需要实现Chart相关的接口接口。如果您觉得还是比较麻烦,那么你可以使用项目默认的pia,然后下载我编写好的Interop(http://code.google.com/p/interopword/),该Interop只包含了Chart相关的接口。

Demo

新建ChartDemo,Word2007插件项目,添加Interop.Word.dll引用和Excel,PIA引用。添加菜单中添加一个按钮,用于触发更新图表事件。项目如图8.

figure 8. Solution.
在ThisAddIn.cs文件中添加代码,用于构建菜单:

protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject() {
    return new Ribbon();
}

核心代码,用于更新图表数据:

public void btnUpdate_Click(Office.IRibbonControl sender) {
            UpdateCharts();
        }

        private void UpdateCharts() {
            ExcelProcessManager pm = new ExcelProcessManager();
            pm.Lock();

            foreach (Word.Bookmark mark in Globals.ThisAddIn.Application.ActiveDocument.Bookmarks) {
                // must cast
                // the inlineshape does not contain the chart property in pia.
                Interop.Word.InlineShapes inlineShapes = (Interop.Word.InlineShapes)mark.Range.InlineShapes;

                if (inlineShapes.Count > 0) {
                    try {
                        object Name = new object();
                        Name = mark.Name;

                        Object[,] obj = new Object[11, 3];
                        // fill data to obj
                        /*     ------------------------------------
                         *     |              |  收入  |  支出   |
                         *     ------------------------------------
                         *     |  2012/03/01  |  1023.2 |  304.23  |
                         *     -------------------------------------
                         *     |  2012/03/02  |  1123.2 |  314.23  |
                         *     -------------------------------------
                         *     |  2012/03/03  |  1223.2 |  674.23  |
                         *     -------------------------------------
                         *     |  2012/03/04  |  1043.2 |  124.23  |
                         *     -------------------------------------
                         *     |  2012/03/05  |  1083.2 |  384.23  |
                         *     -------------------------------------
                         *     |  2012/03/06  |  923.2  |  404.23  |
                         *     -------------------------------------
                         *     |  2012/03/07  |  2023.2 |  305.23  |
                         *     -------------------------------------
                         *     |  2012/03/08  |  1623.2 |  303     |
                         *     -------------------------------------
                         *     |  2012/03/09  |  1403.2 |  314.23  |
                         *     -------------------------------------
                         *     |  2012/03/10  |  1003.2 |  340     |
                         *     -------------------------------------
                         */
                        //添加横向第一列作为标题
                        obj[0, 0] = string.Empty;
                        obj[0, 1] = "收入";
                        obj[0, 2] = "支出";

                        DateTime dt = new DateTime(2012, 3, 1);
                        Random rnd = new Random();
                        int last = 1000;
                        // fill data
                        for (int i = 1; i < 11; i++) {
                            obj[i, 0] = dt.ToString("yyyy/MM/dd");
                            obj[i, 1] = last + rnd.Next(i, 100);
                            obj[i, 2] = last - rnd.Next(i, 100);
                            last = (int)obj[i, 1];
                            dt = dt.AddDays(1);
                        }

                        Interop.Word.Chart chart = inlineShapes[1].Chart;
                        ChartUpdate(chart, Name.ToString(), obj);
                    } catch (Exception ex) {
                        //logger.Warn("Chart update failed!", ex);
                    }
                }
            }

            pm.Release();
        }

        protected void ChartUpdate(Interop.Word.Chart chart, string bookMark, Object[,] dataArr) {
            if (chart == null) {
                //logger.Warn("Word.Chart is null!");
                return;
            }

            if (dataArr == null) {
                //logger.Warn("Data is null!");
                return;
            }

            Object oMissing = System.Reflection.Missing.Value;
            Interop.Word.Chart chrt;
            Microsoft.Office.Interop.Excel.Workbook wb = null;

            Object bk = bookMark;
            try {
                //xlApp.ScreenUpdating = false;
                chrt = chart;

                if (chrt.ChartData == null) {
                    //logger.Warn("chart.ChartData is null!");
                    return;
                }

                chrt.ChartData.Activate();
                wb = (Excel.Workbook)chrt.ChartData.Workbook;

                if (wb == null) {
                    //logger.Warn("chart.ChartData.Workbook is null!");
                    return;
                }
                wb.Application.ScreenUpdating = false;
                wb.Application.WindowState = Microsoft.Office.Interop.Excel.XlWindowState.xlMinimized;

                Microsoft.Office.Interop.Excel.Worksheet wSh = (Excel.Worksheet)wb.Worksheets[1];

                if (wSh == null) {
                    //logger.Warn("chart.ChartData.Workbook.Worksheets[1] is null!");
                    return;
                }

                // save formats
                wSh.Cells.ClearContents();
                Microsoft.Office.Interop.Excel.Range Rng = wSh.get_Range("A1", "A1");
                Rng.get_Resize(dataArr.GetUpperBound(0) + 1, dataArr.GetUpperBound(1) + 1).Value2 = dataArr;
                chrt.SetSourceData("'Sheet1'!" + Rng.get_Resize(dataArr.GetUpperBound(0) + 1, dataArr.GetUpperBound(1) + 1).get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing), Type.Missing);
                chrt.Refresh();
                wb.Application.ScreenUpdating = true;

                wb.Close(Type.Missing, Type.Missing, Type.Missing);
            } catch (System.Runtime.InteropServices.COMException ex) {
                //logger.Warn("Update chart failed!", ex);
                //xlApp.ScreenUpdating = true;
            } finally {
                if (wb != null) {
                    try {
                        Marshal.ReleaseComObject(wb);
                    } catch { }
                }
            }
        }

        private class ExcelProcessManager {
            private bool _exits;
            public ExcelProcessManager() { }

            public void Lock() {
                _exits = Process.GetProcessesByName("EXCEL").Length > 0;
            }

            public void Release() {
                if (_exits)
                    return;

                Process[] excelproc = Process.GetProcessesByName("EXCEL");
                if (excelproc.Length > 0)
                    excelproc[0].Kill();
            }
        }


其中UpdateCharts和ChartUpdate方法用于生成数据,更新图表。ExcelProcessManager类用于管理Excel进程。

下载:

Interop.Word:http://code.google.com/p/interopword/

Demo:chartdemo,chart demo word.docx


分享到:
评论

相关推荐

    poi-word.zip

    解决了word中动态图表的刷新问题,在3.17版本之前poi只支持excel和pptx中刷新

    Excel VBA实用技巧大全 附书源码

    01058获取Excel图表工具栏信息 01059获取Excel常用工具栏信息 01060获取Excel格式工具栏信息 01061获取Excel数据透视表工具栏信息 01062获取Excel的Web工具栏信息 01063获取Excel审阅工具栏信息 01064获取Excel窗体...

    C#开发实例大全(基础卷).软件开发技术联盟(带详细书签) PDF 下载

    主要内容有C#开发环境的使用、C#语言基础应用、字符串处理技术、数组和集合的使用、面向对象编程技术、数据...Word互操作、高效应用Excel、基本图形绘制、图像处理技术、常用图表应用、动画处理技术、音频与视频控制...

    PHP程序开发范例宝典III

    实例036 在下拉菜单中显示数组中的元素 51 实例037 级联菜单的应用 52 实例038 修改数据时下拉列表的默认值为数据库中原数据信息 54 实例039 可输入字符的下拉菜单 56 实例040 应用下拉列表选择所要联机的...

    ACReport中国式报表控件2011(Ver2.3)

    条形码、中式财务帐薄、支持在报表中嵌入Word、Excel文档等。 4. 强大的计算和合计功能。内置表达式解析系统和函数库。 5. 可扩充性,可以在应用程序中给报表引擎扩充函数库、报表样式和单元格样式。 6.支持多种报表...

    delphi 开发经验技巧宝典源码

    0206 如何在DBGrid中实现复制、粘贴功能 137 0207 在DBGrid中将选中的多行删除 137 0208 在DataGrid中如何使标题文字居中 138 0209 如何把ListBox中的内容拖曳到另一个ListBox中 139 0210 把DBGrid中的数据...

    delphi 开发经验技巧宝典源码06

    0206 如何在DBGrid中实现复制、粘贴功能 137 0207 在DBGrid中将选中的多行删除 137 0208 在DataGrid中如何使标题文字居中 138 0209 如何把ListBox中的内容拖曳到另一个ListBox中 139 0210 把DBGrid中的数据...

    北交《计算机应用基础》在线作业二-0003E956.docx

    A:计算机软件系统 B:计算机硬件系统 C:光盘系统 D:UPS系统 答案:A,B 有关EXCEL图表,下面表述错误的是( ) A:要往图表增加一个系列,必须重新建立图表 B:修改了图表数据源单元格的数据,图表会自动跟着刷新 C:要修改...

    C++Builder精彩编程实例集锦的源代码(4,5,6部分).rar

    实例205 如何在程序中实现自定义字段 实例206 如何使用字段拖放功能 实例207 如何为程序添加报表打印功能 实例208 如何使用向导创建打印报表 实例209 如何设置一对多数据库表 实例210 如何设置一对多报表打印...

    C++Builder精彩编程实例集锦的源代码前3部分.rar

    实例051 如何在程序中设置Word文档的字体风格 实例052 如何使用Onldle事件 实例053 如何使程序在循环时响应外界事件 实例054 如何设置程序在系统启动时自动运行 实例055 如何创建多线程程序 实例056 如何创建可...

    北交《计算机应用基础》在线作业二-0004.docx

    下面是段落设置中的对齐方式的有() A:分散对齐 B:居中对齐 C:上对齐 D:下对齐 答案:A,B 有关EXCEL图表,下面表述错误的是( ) A:要往图表增加一个系列,必须重新建立图表 B:修改了图表数据源单元格的数据,图表会...

Global site tag (gtag.js) - Google Analytics