如何以编程方式访问剪贴板中复制的选定内容的地址
本文关键字:地址 复制 编程 方式 剪贴板 访问 | 更新日期: 2023-09-27 18:27:22
以下是我想要实现的目标:
用户复制一个单元格(或范围),比如A3,当她点击按钮时,我需要以编程方式访问该单元格的地址(以创建链接)。
以文本格式访问剪贴板很容易:
string clip;
if (Clipboard.ContainsText()) clip = Clipboard.GetText();
我还发现可以访问不同格式的剪贴板,比如这个
var dataObj = Clipboard.GetDataObject();
var format = DataFormats.CommaSeparatedValue;
if (dataObj != null && dataObj.GetDataPresent(format))
{
var csvData = dataObj.GetData(format);
//...
}
但我一辈子都找不到哪个格式包含链接以及如何获取链接。(我循环浏览了Clipboard.GetDataObject().GetFormats()提供的所有格式,但有些返回的流无法理解。
背景信息:
A。链接必须在那里,因为我可以使用"粘贴链接"来创建绝对参考
B。我在Win7 下使用Excel 2010和VS2010-C#
C。代码在自定义任务窗格中运行
感谢您的帮助!
所以,
感谢所有读到这一点的人。我终于想通了。我的解决方案仍然很尴尬,因为我无法从剪贴板中了解流的实际结构,但我找到了我想要的:
protected override void WndProc(ref Message m)
{
const int WM_PASTE = 0x0302;
var enc = new System.Text.UTF7Encoding();
string buffer, rangeAddress;
if (m.Msg == WM_PASTE)
{
if (Clipboard.ContainsText())
{
string clip = Clipboard.GetText();
var dataObject = Clipboard.GetDataObject();
var mstream = (MemoryStream)dataObject.GetData("Link Source", true);
if(mstream == null) return;
var rdr = new System.IO.StreamReader(mstream, enc, true);
buffer = rdr.ReadToEnd();
buffer = StripWeirdChars(buffer);
int IndexExcl = buffer.IndexOf("!");
if (IndexExcl >= 0)
{
rangeAddress = buffer.Substring(IndexExcl + 1, buffer.Length - IndexExcl - 4);
// do whatever you want to do with it, e.g.:Globals.ThisAddIn.Application.ActiveCell.Value = rangeAddress;
return;
}
}
}
base.WndProc(ref m);
}
}
这里的关键显然是GetData的特殊格式:"链接源"。
读取结果流会生成一个字符串,其中包含许多奇怪的字符,还包含图纸的名称和复制范围的坐标。我用一个简单的去掉了奇怪的字符
public static string StripWeirdChars(string source)
{
string res = "";
foreach (char c in source) if ((int)c >= 32) res += c;
return res;
}
还有一些奇怪的字符我听不懂,但好消息是,在第一个感叹号之后,你会找到范围的地址(后面有一些固定长度的垃圾)。即使该区域是从另一个工作表复制的,即使该工作表的名称中有奇数字符(如德语元音变音符),这也能起作用。
肯定有一个更整洁的解决方案
通过IStream接口从剪贴板获取Excel Range对象
但我发现那里的代码并不完整("显而易见"的部分被遗漏了),由于我的无能和缺乏IStream的经验,我无法让它发挥作用。
任何使用它来获得整洁解决方案的帮助都是值得赞赏的,但我对目前的情况感到满意。谢谢,伙计们。
这只是@drdhk的答案,因为这是在其中一条评论中请求的,以显示它已经得到了回答:
所以,
感谢所有读到这一点的人。我终于想通了。我的解决方案仍然很尴尬,因为我无法从剪贴板中了解流的实际结构,但我找到了我想要的:
protected override void WndProc(ref Message m)
{
const int WM_PASTE = 0x0302;
var enc = new System.Text.UTF7Encoding();
string buffer, rangeAddress;
if (m.Msg == WM_PASTE)
{
if (Clipboard.ContainsText())
{
string clip = Clipboard.GetText();
var dataObject = Clipboard.GetDataObject();
var mstream = (MemoryStream)dataObject.GetData("Link Source", true);
if(mstream == null) return;
var rdr = new System.IO.StreamReader(mstream, enc, true);
buffer = rdr.ReadToEnd();
buffer = StripWeirdChars(buffer);
int IndexExcl = buffer.IndexOf("!");
if (IndexExcl >= 0)
{
rangeAddress = buffer.Substring(IndexExcl + 1, buffer.Length - IndexExcl - 4);
// do whatever you want to do with it, e.g.:Globals.ThisAddIn.Application.ActiveCell.Value = rangeAddress;
return;
}
}
}
base.WndProc(ref m);
}
}
这里的关键显然是GetData的特殊格式:"链接源"。
读取结果流会生成一个字符串,其中包含许多奇怪的字符,还包含图纸的名称和复制范围的坐标。我用一个简单的去掉了奇怪的字符
public static string StripWeirdChars(string source)
{
string res = "";
foreach (char c in source) if ((int)c >= 32) res += c;
return res;
}
还有一些奇怪的字符我听不懂,但好消息是,在第一个感叹号之后,你会找到范围的地址(后面有一些固定长度的垃圾)。即使该区域是从另一个工作表复制的,即使该工作表的名称中有奇数字符(如德语元音变音符),这也能起作用。
肯定有一个更整洁的解决方案
通过IStream接口从剪贴板获取Excel Range对象:(http://www.codeproject.com/Articles/149009/Getting-the-Excel-Range-object-from-the-Clipboard)
但我发现那里的代码并不完整("显而易见"的部分被遗漏了),由于我的无能和缺乏IStream的经验,我无法让它发挥作用。
任何使用它来获得整洁解决方案的帮助都是值得赞赏的,但我对目前的情况感到满意。谢谢,伙计们。
您的方法有一个限制:结果总是一个矩形范围。如果您已经将A1:B2和A4:B5复制到剪贴板中,则您的方法将返回Al:B5这意味着3行包含在结果范围中,而事实上,它不在剪贴板范围中。有更多的剪贴板数据类型包含不那么奇怪的字符,如ObjectLink或Link 在选择范围时按Ctrl键可以选择非矩形范围。