明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 61|回复: 17

求教,C#写插件时遇到的乱码问题。

[复制链接]
发表于 6 小时前 | 显示全部楼层 |阅读模式
从DBText.TextString属性拿文字,然后把文字和其他文字拼接起来组成html格式的String文本放入剪切板。把这个文本在CAD打印出来没问题,但是存入剪切板后中文变成了乱码,数字、英文没问题,怎么解决?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复

使用道具 举报

 楼主| 发表于 6 小时前 | 显示全部楼层
本帖最后由 幽兰聆雨 于 2025-5-23 17:48 编辑
你有种再说一遍 发表于 2025-5-23 17:29
看看你的剪贴板代码,直接存二进制就好了



构建html表格、写入剪切板
  1. public string ToHtml()
  2. {
  3.     StringBuilder sb = new StringBuilder();
  4.     sb.Append("<table border='1'>");
  5.     for (int row = 0; row < RowCount; row++)
  6.     {
  7.         sb.Append("\n<tr>");
  8.         for (int col = 0; col < ColumnCount; col++)
  9.         {
  10.             if (_cells.TryGetValue((row, col), out var cell))
  11.             {
  12.                 if (cell.MergeRange.HasValue)
  13.                 {
  14.                     // 处理合并单元格                           
  15.                     var (mergeRows, mergeCols) = cell.MergeRange.Value;
  16.                     string colspan = mergeCols > 0 ? $" colspan='{mergeCols + 1}'" : "";
  17.                     string rowspan = mergeRows > 0 ? $" rowspan='{mergeRows + 1}'" : "";
  18.                     sb.Append($"<td{colspan}{rowspan}>{cell.Value?.ToString() ?? ""}</td>");
  19.                 }
  20.                 else if (!cell.IsMerged)
  21.                 {
  22.                     sb.Append($"<td>{cell.Value?.ToString() ?? ""}</td>");
  23.                 }
  24.             }
  25.             else
  26.             {
  27.                 sb.AppendLine("<td></td>");
  28.             }
  29.         }
  30.         sb.Append("</tr>");
  31.     }
  32.     sb.Append("\n</table>");
  33.     return sb.ToString();
  34. }
  35. public string ToCsv()
  36. {
  37.     StringBuilder sb = new StringBuilder();
  38.     for (int row = 0; row < RowCount; row++)
  39.     {
  40.         for (int col = 0; col < ColumnCount; col++)
  41.         {
  42.             if (_cells.TryGetValue((row, col), out var cell))
  43.             {
  44.                 sb.Append(cell.Value?.ToString() ?? "");
  45.             }
  46.             else
  47.             {
  48.                 sb.Append("");
  49.             }
  50.             if (col < ColumnCount - 1)
  51.                 sb.Append(",");
  52.         }
  53.         sb.AppendLine();
  54.     }
  55.     return sb.ToString();
  56. }

  57. public void WriteToClipboard()
  58. {
  59.     // 准备数据
  60.     string html = ToHtml();
  61.     // string csv = ToCsv();
  62.     string text = ToString();
  63.     // 创建 DataObject 并添加多格式数据
  64.     DataObject data = new DataObject();

  65.     // 添加HTML
  66.     data.SetData(DataFormats.Html, HtmlOperator.GetFullHtml(html));

  67.     // 添加CSV
  68.     // data.SetData(DataFormats.CommaSeparatedValue, csv);

  69.     // 添加纯文本
  70.     data.SetData(DataFormats.Text, text);

  71.     // 一次性写入剪贴板
  72.     Clipboard.SetDataObject(data, true); // true表示程序退出后数据仍保留
  73. }
复制代码






// 将完善html


  1. public static string GetFullHtml(string htmlContent)
  2. {
  3.     // 包装 HTML 内容为剪切板兼容格式
  4.     string header = $"Version:0.9\nStartHTML:0000000000\nEndHTML:0000000000\nStartFragment:0000000000\nEndFragment:0000000000\n<!DOCTYPE html>\n<html>\n<head>\n<meta charset='utf-8'>\n</head>\n<body>\n<!--StartFragment-->\n";
  5.     string none = "\n<!--读史使人明智,读诗使人灵秀,数学使人周密,科学使人深刻,伦理学使人庄重,逻辑修辞之学使人善辩:凡有所学,皆成性格。-->\n<!--md老是出错,感觉是结束位置计算有问题,加点废话[成功了,果然是结束位置的问题]。-->\n<!--by YLLY-->";
  6.     string footer = $"\n<!--EndFragment-->\n</body>\n</html>";
  7.     string clipboardData =header+ htmlContent + none +footer;

  8.     // 计算各个部分的偏移量
  9.     return UpdateHtmlClipboardOffsets(clipboardData);
  10. }
  11. // 更新 HTML 剪切板格式中的偏移量
  12. private static string UpdateHtmlClipboardOffsets(string fullHtml)
  13. {
  14.     // 计算字节偏移量(UTF-8编码)
  15.     byte[] bytes = Encoding.UTF8.GetBytes(fullHtml);
  16.     int startHtml = Encoding.UTF8.GetString(bytes).IndexOf("<!DOCTYPE html>");
  17.     int startFragment = Encoding.UTF8.GetString(bytes).IndexOf("<!--StartFragment-->") + "<!--StartFragment-->".Length;
  18.     int endFragment = Encoding.UTF8.GetString(bytes).IndexOf("<!--EndFragment-->");
  19.     int endHtml = bytes.Length;

  20.     // 替换占位符
  21.     fullHtml = fullHtml
  22.         .Replace("StartHTML:0000000000", $"StartHTML:{startHtml:D10}")
  23.         .Replace("EndHTML:0000000000", $"EndHTML:{endHtml:D10}")
  24.         .Replace("StartFragment:0000000000", $"StartFragment:{startFragment:D10}")
  25.         .Replace("EndFragment:0000000000", $"EndFragment:{endFragment:D10}");
  26.     return fullHtml;
  27. }

回复 支持 反对

使用道具 举报

 楼主| 发表于 5 小时前 | 显示全部楼层
你有种再说一遍 发表于 2025-5-23 17:50
别用 Clipboard.SetDataObject
去用 Win32API

ai写了一个,还是乱码。。。

粘到WPS里面都没啥问题,粘到excel里面就乱码,麻了
  1. // Win32 API常量
  2. private const uint CF_TEXT = 1;
  3. private static readonly uint CF_HTML = RegisterClipboardFormat("HTML Format");

  4. // Win32 API函数
  5. [DllImport("user32.dll")]
  6. private static extern bool OpenClipboard(IntPtr hWndNewOwner);

  7. [DllImport("user32.dll")]
  8. private static extern bool CloseClipboard();

  9. [DllImport("user32.dll")]
  10. private static extern bool EmptyClipboard();

  11. [DllImport("user32.dll")]
  12. private static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);

  13. [DllImport("kernel32.dll")]
  14. private static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);

  15. [DllImport("kernel32.dll")]
  16. private static extern IntPtr GlobalLock(IntPtr hMem);

  17. [DllImport("kernel32.dll")]
  18. private static extern bool GlobalUnlock(IntPtr hMem);

  19. [DllImport("kernel32.dll")]
  20. private static extern uint RegisterClipboardFormat(string lpszFormat);
  21. public static void WriteToClipboard(string html,string text)
  22. {
  23.      // 打开剪贴板
  24.      if (OpenClipboard(IntPtr.Zero))
  25.      {
  26.          try
  27.          {
  28.              // 清空剪贴板
  29.              EmptyClipboard();

  30.              // 写入HTML格式
  31.              if (!string.IsNullOrEmpty(html))
  32.              {
  33.                  SetClipboardText(html, CF_HTML);
  34.              }

  35.              // 写入纯文本格式
  36.              if (!string.IsNullOrEmpty(text))
  37.              {
  38.                  SetClipboardText(text, CF_TEXT);
  39.              }
  40.          }
  41.          finally
  42.          {
  43.              // 确保关闭剪贴板
  44.              CloseClipboard();
  45.          }
  46.      }
  47. }

  48. private static void SetClipboardText(string text, uint format)
  49. {
  50.      // 分配全局内存
  51.      IntPtr hGlobal = GlobalAlloc(0x2000, (UIntPtr)(text.Length + 1));
  52.      if (hGlobal != IntPtr.Zero)
  53.      {
  54.          try
  55.          {
  56.              // 锁定内存并复制数据
  57.              IntPtr pGlobal = GlobalLock(hGlobal);
  58.              if (pGlobal != IntPtr.Zero)
  59.              {
  60.                  byte[] bytes = Encoding.UTF8.GetBytes(text);
  61.                  Marshal.Copy(bytes, 0, pGlobal, bytes.Length);
  62.                  Marshal.WriteByte(pGlobal + bytes.Length, 0); // 添加null终止符
  63.                  GlobalUnlock(pGlobal);
  64.                  // 设置剪贴板数据
  65.                  SetClipboardData(format, hGlobal);
  66.              }
  67.          }
  68.          catch
  69.          {
  70.              // 发生错误时释放内存
  71.              Marshal.FreeHGlobal(hGlobal);
  72.              throw;
  73.          }
  74.      }
  75. }

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
幽兰聆雨 发表于 2025-5-23 18:56
乱码的地方就是表格内容中的中文部分,中文编码区别怎么对比啊?我刚才试了一下把得到的html文本存到文本 ...

官网:
https://learn.microsoft.com/en-u ... rmat?app_lang=zh-CN

估计是:
在C#代码中将HTML粘贴到Excel出现中文乱码的问题,通常与编码或Excel的解析方式有关。以下是可能的原因和解决方案:

1. HTML未明确指定UTF-8编码

问题:如果生成的HTML没有在<meta>标签中声明UTF-8编码,Excel可能无法正确解析中文字符。

解决方案:确保HTML头部包含:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

C#代码示例:

string html = @"<html><head><meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8""></head><body>中文内容</body></html>";

2. Excel的编码解析问题

问题:即使HTML是UTF-8,Excel在粘贴时可能默认使用其他编码(如ANSI)。

解决方案:

方法1:将HTML保存为.html文件后用Excel直接打开(Excel会识别编码)。

方法2:通过剪贴板API显式设置编码(复杂,需调用Windows API)。

3. 剪贴板数据格式问题

问题:直接复制HTML文本到剪贴板时,可能丢失编码信息。

解决方案:使用Clipboard.SetText并指定格式为TextDataFormat.Html(需处理HTML头):

Clipboard.SetText(html, TextDataFormat.Html);

注意:HTML剪贴板格式需要包含特定的头信息(参考微软文档)。

4. 文件保存时的编码问题

问题:如果代码将HTML保存到文件,需确保文件以UTF-8编码写入。

解决方案:

File.WriteAllText("output.html", html, Encoding.UTF8);

5. Excel的区域设置影响

问题:Excel可能根据系统区域设置自动选择编码。

临时解决:在Excel中手动选择“数据” → “从文本/CSV”导入,并指定UTF-8编码。

推荐调试步骤

检查生成的HTML文件:用记事本/浏览器打开,确认中文正常显示。

直接通过文件导入Excel:测试是否仍乱码。

简化HTML内容:排除CSS/特殊标签的干扰。

如果仍有问题,可以提供部分代码片段,我可以进一步分析具体实现逻辑。
回复 支持 反对

使用道具 举报

发表于 6 小时前 | 显示全部楼层
看看你的剪贴板代码,直接存二进制就好了
回复 支持 反对

使用道具 举报

发表于 6 小时前 | 显示全部楼层
别用 Clipboard.SetDataObject
去用 Win32API
回复 支持 反对

使用道具 举报

 楼主| 发表于 5 小时前 | 显示全部楼层
你有种再说一遍 发表于 2025-5-23 17:29
看看你的剪贴板代码,直接存二进制就好了

想做一个利用剪切板存放html表格,实现将CAD表格输出到excel、word、txt文件的功能,直接存也可以吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 5 小时前 | 显示全部楼层
你有种再说一遍 发表于 2025-5-23 17:50
别用 Clipboard.SetDataObject
去用 Win32API

感谢大佬,我去学一下
回复 支持 反对

使用道具 举报

 楼主| 发表于 5 小时前 | 显示全部楼层
幽兰聆雨 发表于 2025-5-23 18:12
ai写了一个,还是乱码。。。

粘到WPS里面都没啥问题,粘到excel里面就乱码,麻了

哦不对,这是之前的,调试没更新成功
回复 支持 反对

使用道具 举报

发表于 5 小时前 | 显示全部楼层
幽兰聆雨 发表于 2025-5-23 18:18
哦不对,这是之前的,调试没更新成功

你反向操作,从excel复制,然后比较两者数据差异
回复 支持 反对

使用道具 举报

 楼主| 发表于 5 小时前 | 显示全部楼层
你有种再说一遍 发表于 2025-5-23 18:19
你反向操作,从excel复制,然后比较两者数据差异

从excel复制已经试过了,没问题
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-5-23 23:51 , Processed in 0.203321 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表