Selection.CopyAsPicture 只是用来拷贝图片而不是将文字转化为图片

在工作中有客户问下面的代码为什么会返回false。

Word.Selection wdSelection = Application.Selection;
Clipboard.Clear();
Application.ActiveWindow.Selection
.SetRange(Application.ActiveDocument
.Bookmarks["\\Page"].Range.Start,
Application.ActiveDocument.Bookmarks["\\Page"].Range.End - 1);
Application.ActiveWindow.Selection.CopyAsPicture();
bool b = Clipboard.ContainsImage();
if (b)
MessageBox.Show("YES");
else
MessageBox.Show("NO");

我看了一下,原来客户的代码中

Application.ActiveDocument.Bookmarks["\\Page"].Range

是选择当前页(如果当前页只有一个图片时则报错)。所以对于纯文字CopyAsPicture和Copy是没有区别的(Clipboard.ContainsImage() 为false)。

如果当前页面上只有图片,那么Copy是要报错的。这里只能用CopyAsPicture(Clipboard.ContainsImage()为true)。

当文字与图片混排或有两个以上图片时 CopyAsPicture和Copy同样效果(Clipboard.ContainsImage() 为false)。

所以只用下面的代码会返回true。

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Office.Tools.Word;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Office = Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;

namespace WordDocument14
{
    public partial class ThisDocument
    {
        private void ThisDocument_Startup(object sender, System.EventArgs e)
        {
            Word.Selection wdSelection = Application.Selection;
            Clipboard.Clear();
            //注意确保整个文档中只有一张图片,没有其他东西。
            Application.ActiveWindow.Selection
                .SetRange(Application.ActiveDocument.Range().Start,
                Application.ActiveDocument.Range().End - 1);
            Application.ActiveWindow.Selection.Copy();
            bool b = Clipboard.ContainsImage();
            if (b)
                MessageBox.Show("YES");
            else
                MessageBox.Show("NO");
        }

        private void ThisDocument_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisDocument_Startup);
            this.Shutdown += new System.EventHandler(ThisDocument_Shutdown);
        }

        #endregion
    }
}



using Microsoft.Office.Interop.Word; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Word = Microsoft.Office.Interop.Word; namespace MoXiaoZhu.Features.ExportAsPNG { //将表格转换为PNG public class TableConverter { private Word.Application _wordApp; //构造函数 public TableConverter(Word.Application wordApp) { _wordApp = wordApp ?? throw new ArgumentNullException(nameof(wordApp)); } public void ConvertAllTablesToPNG(Document doc) { //空值校验 if (doc == null) { throw new ArgumentNullException(nameof(doc), "转换目标文档不能为空,请先打开Word文档"); } MessageBox.Show($"当前文档表格数量:{doc.Tables.Count}", "调试信息"); //创建表格转换临时目录 //string tempDir = ConverterHelper.CreateTempDirectory("WordTableConverter"); string tempDir = Path.Combine(Path.GetTempPath(), "WordTableConverter"); Directory.CreateDirectory(tempDir); //倒序遍历表格集合 for (int i = doc.Tables.Count; i >= 1; i--) { //获取当前要转换的表格 Table table = doc.Tables[i]; //转换单个为PNG ConvertSingleTableToPNG(table, tempDir, doc, i); } } //转换单个表格为PNG图片 private void ConvertSingleTableToPNG(Table table, string tempDir, Document doc, int tableIndex) { //调试 MessageBox.Show($"进入表格{tableIndex}的转换逻辑,开始执行CopyAsPicture()", "调试-步骤1"); // //空值校验 if (table == null) { throw new ArgumentNullException(nameof(table), "要转换的表格不能为空"); } //获取表格的完整范围 Range tableRange = table.Range; //生成唯一的临时PNG文件名 string tempPngPath = Path.Combine(tempDir, $"table_{Guid.NewGuid()}.png"); try { //提前保存号有效Range Range originalTableRange = table.Range.Duplicate; int tableStartPos = originalTableRange.Start; //检查位置有效性 if (tableStartPos < 0 || tableStartPos > doc.Content.End) tableStartPos = doc.Content.End - 1; //将表格以图片格式复制到剪贴板 //tableRange.Select(); //tableRange.CopyAsPicture(); table.Range.Select(); System.Threading.Thread.Sleep(300); table.Range.Copy(); //计算安全安全的Shape尺寸 float pageWidth = doc.PageSetup.PageWidth; float pageHeight = doc.PageSetup.PageHeight; float leftMargin = Math.Max(doc.PageSetup.LeftMargin, 0); float topMargin = Math.Max(doc.PageSetup.TopMargin, 0); float shapeWidth = Math.Min(pageWidth - leftMargin - doc.PageSetup.RightMargin, pageWidth); float shapeHeight = Math.Max(pageHeight - topMargin - doc.PageSetup.BottomMargin, pageHeight); /* foreach (Row row in table.Rows) { tableHeight += row.Height; } */ Shape tempShape = doc.Shapes.AddShape( Type: 1, Left: leftMargin, Top: topMargin, Width: Math.Max(shapeWidth, 100), Height: Math.Max(shapeHeight, 50)); /* //粘贴为图片 tempShape.TextFrame.TextRange.PasteSpecial( DataType: 3, //粘贴为增强型图元文件 Placement: 0 ); */ //粘贴为图片并处理 tempShape.TextFrame.TextRange.PasteSpecial(DataType: 3); tempShape.TextFrame.TextRange.Copy(); //导出为PNG //tempShape.TextFrame.TextRange.Copy(); if (TryGetEnhancedMetafileFromClipboard(out Image tableImage)) { using (tableImage) { tableImage.Save(tempPngPath, ImageFormat.Png); } } else { throw new InvalidOperationException("无法从剪贴板提取表格图片"); } //清理并替换表格 tempShape.Delete(); //保存表格的起始位置 //int tableStartPos = table.Range.Start; //删除原表格 table.Delete(); //doc.InlineShapes.AddPicture(tempPngPath, false, true, doc.Range(tableStartPos,tableStartPos)); Range insertRange = doc.Range(tableStartPos, tableStartPos); doc.InlineShapes.AddPicture(tempPngPath, false, true, insertRange); MessageBox.Show($"表格{tableIndex}转换成功!", "成功"); /* //从剪贴板提取图片为PNG if (ConverterHelper.TryGetImageFromClipboard(out Image tableImage)) { using (tableImage) { //保存为PNG格式 tableImage.Save(tempPngPath, ImageFormat.Png); } //删除原表格 ReplaceTableWithImage(table, tableRange, tempPngPath, doc); } else { //剪贴板提取失败 throw new InvalidOperationException($"无法从剪贴板提取表格图片(表格索引:{tableIndex})"); } */ } catch (Exception ex) { MessageBox.Show( $"表格{tableIndex}转换失败:\n{ex.Message}\n\n内部异常:{ex.InnerException?.Message}\n堆栈:{ex.StackTrace}", "错误详情" ); } } //从剪贴板提取EMF转为Bitmap private bool TryGetEnhancedMetafileFromClipboard(out Image image) { image = null; IDataObject data = Clipboard.GetDataObject(); //直接读取Word if (data.GetDataPresent(DataFormats.EnhancedMetafile)) { try { //先获取原始数据(句柄或流) object emfData = data.GetData(DataFormats.EnhancedMetafile); //数据是IntPtr if (emfData is IntPtr emfHandle && emfHandle != IntPtr.Zero) { //接管句柄所有权 using (var tempMetafile = new Metafile(emfHandle, true)) using (var ms = new MemoryStream()) { tempMetafile.Save(ms, ImageFormat.Emf); ms.Position = 0; using (var clonedMetafile = new Metafile(ms)) { image = new Bitmap(clonedMetafile.Width, clonedMetafile.Height); using (var g = Graphics.FromImage(image)) { g.Clear(Color.White); g.DrawImage(clonedMetafile, 0, 0); } } } } else if (emfData is Stream stream) { stream.Position = 0; using (var clonedMetafile = new Metafile(stream)) { //var emf = data.GetData(DataFormats.EnhancedMetafile) as Metafile; //if (emf == null) return false; //将EMF渲染成白底Bitmap image = new Bitmap(clonedMetafile.Width, clonedMetafile.Height); using (var g = Graphics.FromImage(image)) { g.Clear(Color.White); g.DrawImage(clonedMetafile, 0, 0); } return true; } } else { //无法识别的数据类型,降级为Bitmap return TryGetBitmapFromClipboard(out image); } return image != null; } catch (Exception ex) { Debug.WriteLine($"EMF处理崩溃:{ex.Message}"); image?.Dispose(); image = null; return TryGetBitmapFromClipboard(out image); } } //直接获取Bitmap return TryGetBitmapFromClipboard(out image); } //备选方案:直接获取Bitmap private bool TryGetBitmapFromClipboard(out Image image) { image = null; IDataObject data = Clipboard.GetDataObject(); if (data.GetDataPresent(DataFormats.Bitmap)) { image = data.GetData(DataFormats.Bitmap) as Image; return image != null; } return false; } //删除原表格并在原位置插入PNG private void ReplaceTableWithImage(Table table, Range insertRange, string pngFilePath, Document doc) { //删除原表格 table.Delete(); //在原表格位置插入内联PNG图片 doc.InlineShapes.AddPicture( FileName: pngFilePath, LinkToFile: false, SaveWithDocument: true, Range: insertRange ); } } } using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing; using System.Runtime.InteropServices; namespace MoXiaoZhu.Features.ExportAsPNG { public static class ConverterHelper { //创建插件临时目录 public static string CreateTempDirectory(string subDirName) { //参数校验:避免创建空名称目录 if (string.IsNullOrWhiteSpace(subDirName)) { throw new ArgumentException("临时子目录名称不能为空或空白", nameof(subDirName)); } //获取系统临时目录 C:\Users\[用户名]\AppData\Local\Temp string systemTempRoot = Path.GetTempPath(); //拼接系统临时目录和自定义子目录 string customTempDir = Path.Combine(systemTempRoot, subDirName); //确保目录存在 if (!Directory.Exists(customTempDir)) { Directory.CreateDirectory(customTempDir); } return customTempDir; } //从系统剪贴板中安全提取图片 public static bool TryGetImageFromClipboard(out Image image) { //初始化输出参数为null image = null; try { //先检查剪贴板是否包含图片数据 if (Clipboard.ContainsImage()) { //从剪贴板获取图片副本 image = Clipboard.GetImage(); //验证图片是否有效 return image != null; } //剪贴板无图片数据,返回false return false; } catch (ExternalException ex) { //处理剪贴板访问异常 MessageBox.Show( text: $"剪贴板访问失败:{ex.Message}\n请关闭占用剪贴板的程序后重试", caption: "操作失败", buttons: MessageBoxButtons.OK, icon: MessageBoxIcon.Error); return false; } catch (Exception ex) { //捕获其它异常 MessageBox.Show( text: $"提取剪贴板图片时发生错误:{ex.Message}", caption: "未知错误", buttons: MessageBoxButtons.OK, icon: MessageBoxIcon.Error); return false; } } } } private void btnConvertToPNG_Click(object sender, RibbonControlEventArgs e) { try { Word.Application wordApp = Globals.ThisAddIn.Application; /* //获取Word应用实例 if (_wordApp == null) { throw new InvalidOperationException("无法获取Word应用程序实例"); } */ //获取活动文档 Document activeDoc = _wordApp.ActiveDocument; if (activeDoc == null) { throw new InvalidOperationException("请先打开一个Word文档再执行转换"); } //实例化TableConverter var tableConverter = new TableConverter(wordApp); //执行表格转PNG tableConverter.ConvertAllTablesToPNG(activeDoc); //执行转换 //imageConverter.ConvertNonPNGImagesToPNG(activeDoc); //tableConverter.ConvertAllTablesToPNG(activeDoc); //_wordApp.StatusBar = "转换完成!所有非PNG图片和表格已成功转换为PNG格式"; MessageBox.Show("所有表格已成功转换为PNG图片!", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { //异常处理 MessageBox.Show( text: $"转换过程中发生错误:{ex.Message}\n\n建议:\n1. 关闭占用剪贴板的程序\n2. 确保文档未被只读保护\n3. 重启Word后重试", caption: "转换失败", buttons: MessageBoxButtons.OK, icon: MessageBoxIcon.Error ); } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using Microsoft.Office.Interop.Word; using Microsoft.Office.Core; namespace MoXiaoZhu.Features.ExportAsPNG { //将非PNG格式转换为PNG格式 public class ImageConverter { public void ConvertNonPNGImagesToPNG(Document doc) { if (doc == null) throw new ArgumentNullException(nameof(doc), "文档对象不能为空"); //创建临时目录 string tempDir = ConverterHelper.CreateTempDirectory("WordImageConverter"); //倒序遍历 ProcessInlineImages(doc, tempDir); ProcessFloatingImages(doc, tempDir); } //处理嵌入式图片 private void ProcessInlineImages(Document doc, string tempDir) { //从后往前遍历 for (int i = doc.InlineShapes.Count; i >= 1; i--) { InlineShape inlineShape = doc.InlineShapes[i]; //仅处理嵌入型图片 if (inlineShape.Type == WdInlineShapeType.wdInlineShapePicture) { ConvertSingleImage(inlineShape, tempDir, doc); } } } //处理浮动图片 private void ProcessFloatingImages(Document doc, string tempDir) { //从后往前遍历浮动图片 for (int i = doc.Shapes.Count; i >= 1; i--) { Microsoft.Office.Interop.Word.Shape shape = doc.Shapes[i]; //仅处理图片类型的浮动形状 if (shape.Type == MsoShapeType.msoPicture) { ConvertSingleImage(shape, tempDir, doc); } } } //转换单个图片为PNG private void ConvertSingleImage(object shape, string tempDir, Document doc) { //获取图片对应的文档范围 Range imageRange = GetImageRange(shape); //检查是否已为PNG格式 if (!IsPNGImage(shape)) { string tempPngPath = Path.Combine(tempDir, $"img_{Guid.NewGuid()}.png"); try { //将图片复制为图片格式到剪贴板 imageRange.CopyAsPicture(); //从剪贴板获取并保存为PNG if (ConverterHelper.TryGetImageFromClipboard(out var pngImage)) { using (pngImage) { pngImage.Save(tempPngPath, System.Drawing.Imaging.ImageFormat.Png); } //删除原图,插入新图 ReplaceOriginalImage(shape, imageRange, tempPngPath, doc); } } catch (Exception ex) { throw new InvalidOperationException($"转换图片失败:{ex.Message}", ex); } } } //获取图片对应的文档范围 private Range GetImageRange(object shape) { switch (shape) { case InlineShape inlineShape: return inlineShape.Range; case Microsoft.Office.Interop.Word.Shape floatingShape: return floatingShape.Anchor; default: throw new ArgumentException($"不支持的图片类型:{shape.GetType().FullName}", nameof(shape)); } } //检查是否已经为PNG格式 private bool IsPNGImage(object shape) { try { if (shape is InlineShape inlineShape) { //获取图片的链接路径 string sourcePath = inlineShape.LinkFormat?.SourcePath ?? string.Empty; return !string.IsNullOrEmpty(sourcePath) && Path.GetExtension(sourcePath).Equals(".png", StringComparison.OrdinalIgnoreCase); } return false; } catch { return false; } } //替换原来图片为新图PNG private void ReplaceOriginalImage(object originalShape, Range targetRange, string pngFilePath, Document doc) { //删除原图片 targetRange.Delete(); //根据图片类型插入新的PNG图片 if (originalShape is InlineShape) { //插入嵌入式 doc.InlineShapes.AddPicture( FileName: pngFilePath, LinkToFile: false, SaveWithDocument: true, Range: targetRange ); } else if (originalShape is Microsoft.Office.Interop.Word.Shape) { //插入浮动型 doc.Shapes.AddPicture( FileName: pngFilePath, LinkToFile: false, SaveWithDocument: true, Anchor: targetRange ); } } } } 这是上述报错项目的全部代码,请分析一下应该如何解决这个报错问题,之前shape直接导出emf数据的方法因版本问题,部分枚举不存在不可行
最新发布
11-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值