gpt4 book ai didi

c# - 复制 Excel 图表并将其移动到另一个工作表

转载 作者:行者123 更新时间:2023-11-30 20:21:32 25 4
gpt4 key购买 nike

我正在使用 C# Excel 互操作,我想从一个工作表创建图表的副本,但我想在另一张工作表上创建该副本。我尝试了以下方法:

Excel.ChartObject chartTemplate = (Excel.ChartObject)sheetSource.ChartObjects("chart 1");
object o = chartTemplate.Duplicate();
Excel.ChartObject chart = (Excel.ChartObject)sheetSource.ChartObjects("chart 2");
chart.Name = "Skew" + expiry.ToString("MMMyy");
range = sheetDestination.Range["T" + chartRowCoutner.ToString()];

chart.Chart.Location(Excel.XlChartLocation.xlLocationAsObject, range);

但是当我尝试这样做时,最后一行抛出错误:

An unhandled exception of type 'System.Exception' occurred in projectname.exe

Additional information: Error reading Excel file C:\ ...the file path...\template.xlsx: Value does not fall within the expected range.

我也试过传递一个工作表而不是一个范围:

chart.Chart.Location(Excel.XlChartLocation.xlLocationAsObject, sheetDestination);

但这给出了同样的错误。我不明白错误的原因或如何修复它/绕过它。

我尽量避免将剪贴板带入这里,但即使我尝试复制和粘贴,我仍然只能将其作为图像粘贴,这确实不理想:

Excel.ChartArea chartArea = chart.ChartArea;
chartArea.Copy();
range = sheetDestination.Range["T" + chartRowCoutner.ToString()]; // Note that chart is not on the sheet sheetDestination
range.PasteSpecial(Excel.XlPasteType.xlPasteAll);

我现在能想到的唯一其他解决方案是在 VBA 中执行此操作,然后通过互操作执行宏。但可以肯定的是,只需使用互操作而不使用剪贴板,它就可以以一种干净的方式完成。

最佳答案

您已经有了解决方案,但我不会给您一天的鱼,而是给您一个正确的答案,这将帮助您完成任何 C# Excel 编码任务。

Excel 的 C# Interop 模型与 VBA Excel 模型几乎相同。

这意味着将 VBA 录制的宏转换为 C# 是微不足道的。让我们通过将图表移动到不同的工作表这样的练习来尝试一下。


在 Excel 的“开发人员”选项卡中,单击“录制宏”> 右键单击​​“图表”> 选择“移动图表”> 选择“对象在:Sheet2”> 单击“确定”> 单击“停止宏录制”。

enter image description here

要查看录制的宏,请按 Alt + F11 调出 VB 编辑器:

enter image description here

请看上面的屏幕截图,VBA 如何向您显示 Location() 的第二个参数是 Name,它实际上是一个字符串参数...

让我们将此 VBA 宏转换为 C#:

enter image description here

@Ama 编辑

下面的建议已经过时了,实际上没有必要担心释放 COM 对象,这是在 RELEASE 模式下自动完成的 (DEBUG mode does not)。参见 Hans Passant's answer to "Clean up Excel Interop Objects with IDisposable" .


这里的诀窍是:永远不要对 com 对象使用 2 个点。

注意我是怎么写的:

var sheetSource = workbookWrapper.ComObject.Sheets["Sheet1"];

但是那有两个点,所以我改为这样写:

var workbookComObject = workbookWrapper.ComObject;
var sheetSource = workbookComObject.Sheets["Sheet1"];

引用:How do I properly clean up Excel interop objects?

您将在上面的 QA 中看到 AutoReleaseComObject 代码,项目类似于 VSTOContrib使用。

完整代码如下:

using Microsoft.Office.Interop.Excel;
...
var missing = Type.Missing;
using (AutoReleaseComObject<Microsoft.Office.Interop.Excel.Application> excelApplicationWrapper = new AutoReleaseComObject<Microsoft.Office.Interop.Excel.Application>(new Microsoft.Office.Interop.Excel.Application()))
{
var excelApplicationWrapperComObject = excelApplicationWrapper.ComObject;
excelApplicationWrapperComObject.Visible = true;

var excelApplicationWrapperComObjectWkBooks = excelApplicationWrapperComObject.Workbooks;
try
{
using (AutoReleaseComObject<Workbook> workbookWrapper = new AutoReleaseComObject<Workbook>(excelApplicationWrapperComObjectWkBooks.Open(@"C:\Temp\ExcelMoveChart.xlsx", false, false, missing, missing, missing, true, missing, missing, true, missing, missing, missing, missing, missing)))
{
var workbookComObject = workbookWrapper.ComObject;
Worksheet sheetSource = workbookComObject.Sheets["Sheet1"];
ChartObject chartObj = (ChartObject)sheetSource.ChartObjects("Chart 3");
Chart chart = chartObj.Chart;
chart.Location(XlChartLocation.xlLocationAsObject, "Sheet2");

ReleaseObject(chart);
ReleaseObject(chartObj);
ReleaseObject(sheetSource);

workbookComObject.Close(false);
}
}
finally
{
excelApplicationWrapperComObjectWkBooks.Close();
ReleaseObject(excelApplicationWrapperComObjectWkBooks);

excelApplicationWrapper.ComObject.Application.Quit();
excelApplicationWrapper.ComObject.Quit();
ReleaseObject(excelApplicationWrapper.ComObject.Application);
ReleaseObject(excelApplicationWrapper.ComObject);

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}

private static void ReleaseObject(object obj)
{
try
{
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 0);
obj = null;
}
catch (Exception ex)
{
obj = null;
Console.WriteLine("Unable to release the Object " + ex.ToString());
}
}

我知道释放所有对象,使用 GC.Collect 并且在分配时不使用两个点似乎超出了顶部但至少当我退出 Excel 实例时进程被释放,我不必以编程方式终止 Excel过程!

引用:Microsoft KB: Office application does not quit after automation from .NET client

关于c# - 复制 Excel 图表并将其移动到另一个工作表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33782622/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com