0

我正在尝试将 pdf 文件嵌入到 OPEN XML 文档中。这需要创建 *.bin 文件。我不想使用自动化。

我从这个问题中采取的方法适用于我测试过的所有文件类型,除了 *.pdf。

由于某种原因,pdf 文件总是从 OleCreateFromFile(..) 获得结果为 0x80004005 并且 pOle 为 NULL。

我是调用和 OLE 领域的新手。这种方法不适用于 PDF 的原因可能是什么?(我有最新的Adobe Reader,Win8,调用Ole32.dll,项目构建目标是x86,我测试调用CoUninitialize()和CoInitializeEx((System.IntPtr)null,OLE32.CoInit.ApartmentThreaded),我能够嵌入MSWORD 应用程序中的 pdf 文件)。

这是我使用的一个函数:

public static string ExportOleFile(string _inputFileName, string oleOutputFileName, string emfOutputFileName)
        {
            StringBuilder resultString = new StringBuilder();           
            string newInput = MultibyteToUnicodeNETOnly(_inputFileName, 1252);

            Microsoft.VisualStudio.OLE.Interop.IStorage storage;
            var result = OLE32.StgCreateStorageEx(oleOutputFileName,
                Convert.ToInt32(OLE32.STGM.STGM_READWRITE | OLE32.STGM.STGM_SHARE_EXCLUSIVE | OLE32.STGM.STGM_CREATE | OLE32.STGM.STGM_TRANSACTED),
                Convert.ToInt32(OLE32.STGFMT.STGFMT_DOCFILE),
                0,
                IntPtr.Zero,
                IntPtr.Zero,
                ref OLE32.IID_IStorage,
                out storage
            );//vytvoří bin

            resultString.AppendLine("CreateStorageEx Result: " + result.ToString());

            var CLSID_NULL = Guid.Empty;


            Microsoft.VisualStudio.OLE.Interop.FORMATETC f = new FORMATETC();
            Microsoft.VisualStudio.OLE.Interop.IOleObject pOle;
            result = OLE32.OleCreateFromFile(
                ref CLSID_NULL,
                newInput,
                ref OLE32.IID_IOleObject,
                (uint)Microsoft.VisualStudio.OLE.Interop.OLERENDER.OLERENDER_NONE,
                ref f,
                null,
                storage,
                out pOle
            );

            resultString.AppendLine("OleCreateFromFile Result: " + result.ToString());
            try
            {

                result = OLE32.OleRun(pOle);
            }
            catch (Exception ex)
            {
                resultString.AppendLine(ex.ToString());
                return resultString.ToString();
            }

            resultString.AppendLine("OleRun Result: " + result.ToString());

            try
            {

                IntPtr unknownFromOle = Marshal.GetIUnknownForObject(pOle);
                IntPtr unknownForDataObj;
                Marshal.QueryInterface(unknownFromOle, ref OLE32.IID_IDataObject, out unknownForDataObj);
                var pdo = Marshal.GetObjectForIUnknown(unknownForDataObj) as System.Runtime.InteropServices.ComTypes.IDataObject;

                var fetc = new System.Runtime.InteropServices.ComTypes.FORMATETC();

                fetc.cfFormat = (short)OLE32.CLIPFORMAT.CF_ENHMETAFILE;
                fetc.dwAspect = System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT;
                fetc.lindex = -1;
                fetc.ptd = IntPtr.Zero;
                fetc.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_ENHMF;

                var stgm = new System.Runtime.InteropServices.ComTypes.STGMEDIUM();
                stgm.unionmember = IntPtr.Zero;
                stgm.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_ENHMF;
                pdo.GetData(ref fetc, out stgm);

                var hemf = GDI32.CopyEnhMetaFile(stgm.unionmember, emfOutputFileName);
                storage.Commit((int)OLE32.STGC.DEFAULT);

                pOle.Close(0);
                GDI32.DeleteEnhMetaFile(stgm.unionmember);
                GDI32.DeleteEnhMetaFile(hemf);
            }
            catch (Exception ex)
            {
                resultString.AppendLine(ex.ToString());
                return resultString.ToString();
            }         
            return resultString.ToString();
        }
4

1 回答 1

0

实际上,要在 OpenXML 中嵌入文件,就必须使用旧的 OLE 函数。没有其他办法,因为您需要获得两件:

  • 将要嵌入的文件
  • 显示文件内容的图片,通常是第一页的截图

我确实写了一篇博客文章:Embedd pdf into powerpoint by usage of openxml。这不完全是您的要求,但它的工作原理相同。

pdf 在嵌入方面存在两个问题:

  • 嵌入的 pdf 文档与原始 pdf 文件具有不同的内容。对于我知道的所有其他 OLE 格式(excel、word、powerpoint...),情况并非如此。你可以只使用硬盘上的文件,对于pdf你不能。
  • 您需要拍摄第一页的照片。您可以使用 pdfium 或类似工具 - 有相当多的工具可用于渲染 pdf,但 adobe reader 是免费的,并且可以 100% 完成工作。
于 2016-04-04T14:33:32.210 回答