将Excel图表从Excel导入到PowerPoint会导致某些计算机上出现“RPC_E_SERVERFAULT”

这是一个令人恼火的。 我创建了一种方法将工作簿中的所有Excel图表复制到PowerPoint幻灯片。

public int ImportExcelChartsFromWorkbookToSlides(int startingSlideIndex, string workbookPath, string[] slideTitles, int chartPosTop, int chartPosLeft = 10, int titleWidth = 680, int titleHeight = 20, int titlePosTop = 90, int titlePosLeft = 20, int titleFontSize = 18) { int slideIndex = startingSlideIndex; int titleIndex = 0; EXCL.Application objExclApp = new EXCL.Application(); EXCL.Workbook objWorkbook = objExclApp.Workbooks.Open(workbookPath, Editable: false); foreach (EXCL.Worksheet objSheet in objWorkbook.Worksheets) { foreach (EXCL.ChartObject objChart in objSheet.ChartObjects()) { AddBlankSlide(slideIndex); AddTextBox(titleWidth.ToString(), titleHeight.ToString(), titlePosTop.ToString(), titlePosLeft.ToString()); AddTextBoxParagraph(slideTitles[titleIndex], fontSize: titleFontSize.ToString(), useThemeFont: true); // Copy Chart from Sheet to Slide objChart.CopyPicture(); PPT.ShapeRange objShapeRange = objSlide.Shapes.Paste(); objShapeRange.Left = chartPosLeft; objShapeRange.Top = chartPosTop; slideIndex++; titleIndex++; Marshal.ReleaseComObject(objChart); Marshal.ReleaseComObject(objShapeRange); } Marshal.ReleaseComObject(objSheet); } objWorkbook.Close(); objExclApp.Quit(); Marshal.ReleaseComObject(objWorkbook); Marshal.ReleaseComObject(objExclApp); objWorkbook = null; objExclApp = null; return slideIndex; } 

通常情况下,这在我的机器上完美运行,但有些用户从此方法报告RPC_E_SERVERFAULT 。 (HRESULT:0x80010105)

此方法中的某处导致问题。 这或者是不同的办公室安装,内存问题或导致问题的加载项的问题。 我已经在其他几台机器上尝试了这个,但它们仍然有效。

RPC_E_SERVERFAULT很难诊断,很难诊断。 Excel崩溃时出现此错误。 没有任何细节,这种崩溃应该由应用程序本身报告。 哪个没有发生,更糟糕的是,即使发生了一些相当糟糕的事情,Excel也会继续运行。 在你拿到出现这个问题的机器之前,你不可能在这样的事故上取得任何真正的进展。

然而,找到其他受害者并不难,只有Google“chartobject rpc_e_serverfault”。 他们看起来都像你的。 减去一个好的解决方案。

我对潜在问题有一个相当好的理论。 问题是微软已经设法使Office互操作接口兼容已有19年了。 相当令人惊叹的成就,以及每个人都认为理所当然的东西,即使它没有任何微不足道的东西,但它已经耗尽了气体。 作为常见的麻烦制造者,图表值得注意。

看一下IChartObject接口的定义。 在Office 2013和2003定义之间来回翻转。 并注意神秘的_Copy()方法的添加。 因为已经存在Copy()方法,所以看起来完全没有必要。 并且没有证件。

这是一个问题。 如果您在VS中使用GoTo Definition查看接口定义,请注意它是接口表中的第二个方法。 这是一个很大的问题。 它打破了界面的二进制兼容性。

后果是可怕的,如果您使用Office 2013的互操作库来构建您的程序,并且用户在他的机器上有Office 2003(或2007,无法分辨),那么程序中的CopyPicture()调用将调用完全错误的实现方法。 推测是Cut(),一种不带参数的方法。 这是非常糟糕的,如果方法本身没有内爆,那么堆栈不平衡会导致各种各样的破坏。 RPC_E_SERVERFAULT是预期的结果。

因此,一个可行的理论是这种炸弹在具有旧Office版本的机器上。 除了构建使用2003互操作库的程序的另一个版本并指示IT人员在分发它时要小心,你几乎无能为力。 升级机器是迄今为止简单的解决方法。

我使用ChartObject.Copy()方法有类似的问题。 当我尝试使应用程序可见以查看是否有任何对话框显示时,它实际上最终修复了RPC错误。 作为一种解决方法,我在下面打开了excel应用程序并使其在运行ChartObject.Copy()和其他操作之前暂时可见但最小化。

 var excel = new Microsoft.Office.Interop.Excel.Application(); excel.WindowState = Microsoft.Office.Interop.Excel.XlWindowState.xlMinimized; excel.Visible = true; var workbooks = excel.Workbooks; var workbook = workbooks.Open(excelFilePath, ReadOnly: false); excel.Visible = false;