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

本文关键字:工作簿 断开 链接 外部 复制 Excel | 更新日期: 2023-09-27 18:22:09

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

    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和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)
        {
            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范围?

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

我看错了Series的成员。我需要更改的成员是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;
            }
        }
    }

编辑:但是有更好的方法可以去除所有外部链接。它比em>更快、更全面。我只是在复制了所有的表格和图表后称之为:

    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);
        }
    }

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

无法将"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);
                }
            }
        }
    }