如何将Excel图表复制到新工作簿并中断外部链接

时间:2014-09-16 04:05:10

标签: c# vsto excel-interop

我使用以下代码将所有图表从一个工作簿复制到另一个工作簿:

    using Excel = Microsoft.Office.Interop.Excel;
    ...
    private static void CopyCharts(Excel.Workbook wbIn, Excel.Workbook wbOut)
    {
        Excel.Worksheet wsOutAfter = (Excel.Worksheet)wbOut.Sheets["Last Sheet"];
        foreach (Excel.Chart c in wbIn.Charts)
        {
            c.Copy(Type.Missing, wsOutAfter);
        }
    }

每个图表引用源工作簿中的工作表上的数据(" wbIn")。这样做的问题是Chart.Copy命令保留了这些链接,因此现在目标工作簿中的图表(" wbOut")包含指向wbIn的外部链接。

为了摆脱外部链接,我想迭代每个目标图表中的所有系列,并更新XValues和值以指向目标数据表。这就是我到目前为止所拥有的:

    private static void CopyCharts(Excel.Workbook wbIn, Excel.Workbook wbOut)
    {
        Excel.Worksheet wsOutAfter = (Excel.Worksheet)wbOut.Sheets["Plot Items"];
        foreach (Excel.Chart c in wbIn.Charts)
        {
            string chartName = c.Name;
            c.Copy(Type.Missing, wsOutAfter);
            Excel.SeriesCollection sc = (Excel.SeriesCollection)c.SeriesCollection();
            foreach (Excel.Series s in sc)
            {
                Excel.Range r = (Excel.Range)s.XValues;
                // get string representing range, modify it and set corresponding
                // series in wbOut.Charts.Item[chartName] to something appropriate
            }
        }
    }

但演员抛出异常:

System.InvalidCastException: Unable to cast object of type 'System.Object[*]' to type 'Microsoft.Office.Interop.Excel.Range'.

如何获取和修改Series.XValues和.Values范围?

2 个答案:

答案 0 :(得分:0)

我正在看错误的系列成员。我需要更改的成员是Series.Formula,而不是Series.XValues和.Values。这是我最终得到的结果,迭代输出工作簿中的图表,然后迭代他们的系列并使用正则表达式删除外部链接文本:

    private static void CopyCharts(Excel.Workbook wbIn, Excel.Workbook wbOut)
    {
        Excel.Worksheet wsOutAfter = (Excel.Worksheet)wbOut.Sheets["Plot Items"];
        foreach (Excel.Chart c in wbIn.Charts)
        {
            c.Copy(Type.Missing, wsOutAfter);
        }

        // break external links in new charts
        Regex externalLink = new Regex(@"\[" + wbIn.Name + @"\]");
        foreach (Excel.Chart cOut in wbOut.Charts)
        {
            Excel.SeriesCollection scOut = (Excel.SeriesCollection)cOut.SeriesCollection();
            foreach (Excel.Series sOut in scOut)
            {
                string formula = sOut.Formula;
                formula = externalLink.Replace(formula, "");
                sOut.Formula = formula;
            }
        }
    }

编辑:但是有更好的方法可以摆脱所有外部链接。它的很多更快更全面。我只是在复制完所有的图表和图表后调用它:

    private static void BreakAllExternalLinks(Excel.Workbook wbIn, Excel.Workbook wbOut)
    {
        Array links = (Array)wbOut.LinkSources(Excel.XlLink.xlExcelLinks);

        foreach (object o in links)
        {
            string link = o as string;
            if (link == wbIn.FullName)
                wbOut.ChangeLink(link, wbOut.FullName, Excel.XlLinkType.xlLinkTypeExcelLinks);
        }
    }

答案 1 :(得分:0)

我尝试使用建议的方法,但有一个例外:

  

无法转换类型' System.Object [*]'输入' System.Object []'

在C#4.0中,您需要先转换为对象。我的诗句很适合我:

private static void BreakAllExternalLinks(Excel.Workbook wbFrom, Excel.Workbook wbTo)
    {
        Array links = (Array)((object)wbTo.LinkSources(Excel.XlLink.xlExcelLinks));
        if (links != null)
        {
            foreach (object o in links)
            {
                string link = o as string;
                if (link == wbFrom.FullName)
                {
                    wbTo.ChangeLink(link, wbTo.FullName, Excel.XlLinkType.xlLinkTypeExcelLinks);
                }
            }
        }
    }