求教,C#写插件时遇到的乱码问题。
从DBText.TextString属性拿文字,然后把文字和其他文字拼接起来组成html格式的String文本放入剪切板。把这个文本在CAD打印出来没问题,但是存入剪切板后中文变成了乱码,数字、英文没问题,怎么解决? 本帖最后由 幽兰聆雨 于 2025-5-23 17:48 编辑你有种再说一遍 发表于 2025-5-23 17:29
看看你的剪贴板代码,直接存二进制就好了
构建html表格、写入剪切板
public string ToHtml()
{
StringBuilder sb = new StringBuilder();
sb.Append("<table border='1'>");
for (int row = 0; row < RowCount; row++)
{
sb.Append("\n<tr>");
for (int col = 0; col < ColumnCount; col++)
{
if (_cells.TryGetValue((row, col), out var cell))
{
if (cell.MergeRange.HasValue)
{
// 处理合并单元格
var (mergeRows, mergeCols) = cell.MergeRange.Value;
string colspan = mergeCols > 0 ? $" colspan='{mergeCols + 1}'" : "";
string rowspan = mergeRows > 0 ? $" rowspan='{mergeRows + 1}'" : "";
sb.Append($"<td{colspan}{rowspan}>{cell.Value?.ToString() ?? ""}</td>");
}
else if (!cell.IsMerged)
{
sb.Append($"<td>{cell.Value?.ToString() ?? ""}</td>");
}
}
else
{
sb.AppendLine("<td></td>");
}
}
sb.Append("</tr>");
}
sb.Append("\n</table>");
return sb.ToString();
}
public string ToCsv()
{
StringBuilder sb = new StringBuilder();
for (int row = 0; row < RowCount; row++)
{
for (int col = 0; col < ColumnCount; col++)
{
if (_cells.TryGetValue((row, col), out var cell))
{
sb.Append(cell.Value?.ToString() ?? "");
}
else
{
sb.Append("");
}
if (col < ColumnCount - 1)
sb.Append(",");
}
sb.AppendLine();
}
return sb.ToString();
}
public void WriteToClipboard()
{
// 准备数据
string html = ToHtml();
// string csv = ToCsv();
string text = ToString();
// 创建 DataObject 并添加多格式数据
DataObject data = new DataObject();
// 添加HTML
data.SetData(DataFormats.Html, HtmlOperator.GetFullHtml(html));
// 添加CSV
// data.SetData(DataFormats.CommaSeparatedValue, csv);
// 添加纯文本
data.SetData(DataFormats.Text, text);
// 一次性写入剪贴板
Clipboard.SetDataObject(data, true); // true表示程序退出后数据仍保留
}
// 将完善html
public static string GetFullHtml(string htmlContent)
{
// 包装 HTML 内容为剪切板兼容格式
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";
string none = "\n<!--读史使人明智,读诗使人灵秀,数学使人周密,科学使人深刻,伦理学使人庄重,逻辑修辞之学使人善辩:凡有所学,皆成性格。-->\n<!--md老是出错,感觉是结束位置计算有问题,加点废话[成功了,果然是结束位置的问题]。-->\n<!--by YLLY-->";
string footer = $"\n<!--EndFragment-->\n</body>\n</html>";
string clipboardData =header+ htmlContent + none +footer;
// 计算各个部分的偏移量
return UpdateHtmlClipboardOffsets(clipboardData);
}
// 更新 HTML 剪切板格式中的偏移量
private static string UpdateHtmlClipboardOffsets(string fullHtml)
{
// 计算字节偏移量(UTF-8编码)
byte[] bytes = Encoding.UTF8.GetBytes(fullHtml);
int startHtml = Encoding.UTF8.GetString(bytes).IndexOf("<!DOCTYPE html>");
int startFragment = Encoding.UTF8.GetString(bytes).IndexOf("<!--StartFragment-->") + "<!--StartFragment-->".Length;
int endFragment = Encoding.UTF8.GetString(bytes).IndexOf("<!--EndFragment-->");
int endHtml = bytes.Length;
// 替换占位符
fullHtml = fullHtml
.Replace("StartHTML:0000000000", $"StartHTML:{startHtml:D10}")
.Replace("EndHTML:0000000000", $"EndHTML:{endHtml:D10}")
.Replace("StartFragment:0000000000", $"StartFragment:{startFragment:D10}")
.Replace("EndFragment:0000000000", $"EndFragment:{endFragment:D10}");
return fullHtml;
}
你有种再说一遍 发表于 2025-5-23 17:50
别用 Clipboard.SetDataObject
去用 Win32API
ai写了一个,还是乱码。。。
粘到WPS里面都没啥问题,粘到excel里面就乱码,麻了
// Win32 API常量
private const uint CF_TEXT = 1;
private static readonly uint CF_HTML = RegisterClipboardFormat("HTML Format");
// Win32 API函数
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
private static extern bool CloseClipboard();
private static extern bool EmptyClipboard();
private static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
private static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
private static extern IntPtr GlobalLock(IntPtr hMem);
private static extern bool GlobalUnlock(IntPtr hMem);
private static extern uint RegisterClipboardFormat(string lpszFormat);
public static void WriteToClipboard(string html,string text)
{
// 打开剪贴板
if (OpenClipboard(IntPtr.Zero))
{
try
{
// 清空剪贴板
EmptyClipboard();
// 写入HTML格式
if (!string.IsNullOrEmpty(html))
{
SetClipboardText(html, CF_HTML);
}
// 写入纯文本格式
if (!string.IsNullOrEmpty(text))
{
SetClipboardText(text, CF_TEXT);
}
}
finally
{
// 确保关闭剪贴板
CloseClipboard();
}
}
}
private static void SetClipboardText(string text, uint format)
{
// 分配全局内存
IntPtr hGlobal = GlobalAlloc(0x2000, (UIntPtr)(text.Length + 1));
if (hGlobal != IntPtr.Zero)
{
try
{
// 锁定内存并复制数据
IntPtr pGlobal = GlobalLock(hGlobal);
if (pGlobal != IntPtr.Zero)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
Marshal.Copy(bytes, 0, pGlobal, bytes.Length);
Marshal.WriteByte(pGlobal + bytes.Length, 0); // 添加null终止符
GlobalUnlock(pGlobal);
// 设置剪贴板数据
SetClipboardData(format, hGlobal);
}
}
catch
{
// 发生错误时释放内存
Marshal.FreeHGlobal(hGlobal);
throw;
}
}
}
幽兰聆雨 发表于 2025-5-23 18:56
乱码的地方就是表格内容中的中文部分,中文编码区别怎么对比啊?我刚才试了一下把得到的html文本存到文本 ...
官网:
https://learn.microsoft.com/en-us/windows/win32/dataxchg/html-clipboard-format?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/特殊标签的干扰。
如果仍有问题,可以提供部分代码片段,我可以进一步分析具体实现逻辑。 看看你的剪贴板代码,直接存二进制就好了 别用 Clipboard.SetDataObject
去用 Win32API 你有种再说一遍 发表于 2025-5-23 17:29
看看你的剪贴板代码,直接存二进制就好了
想做一个利用剪切板存放html表格,实现将CAD表格输出到excel、word、txt文件的功能,直接存也可以吗? 你有种再说一遍 发表于 2025-5-23 17:50
别用 Clipboard.SetDataObject
去用 Win32API
感谢大佬,我去学一下 幽兰聆雨 发表于 2025-5-23 18:12
ai写了一个,还是乱码。。。
粘到WPS里面都没啥问题,粘到excel里面就乱码,麻了
哦不对,这是之前的,调试没更新成功 幽兰聆雨 发表于 2025-5-23 18:18
哦不对,这是之前的,调试没更新成功
你反向操作,从excel复制,然后比较两者数据差异 你有种再说一遍 发表于 2025-5-23 18:19
你反向操作,从excel复制,然后比较两者数据差异
从excel复制已经试过了,没问题
页:
[1]
2