这就是我想要实现的目标:
用户复制一个单元格(或范围),比如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()提供的所有格式,但是有些返回了我无法理解的不可思议的流。
背景资料:
一个。链接必须在那里,因为我可以使用“粘贴链接”来创建绝对引用
B中。我正在使用Excel 2010和VS2010 - Win7下的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;
}
还有一些奇怪的字符我无法理解,但好消息是在第一个感叹号后你会找到该范围的地址(带有一些固定长度的尾随垃圾)。即使从另一个工作表复制范围,即使此工作表的名称中有奇怪的字符(如德语变音符号),这也可以工作。
当然有一个更简洁的解决方案
Getting the Excel Range object from the Clipboard through the IStream interface
但是我发现那里的代码并不完整(“明显的”部分被遗漏了),由于我的无能和缺乏IStream开始的经验,我无法使用它。
使用它来获得一个简洁的解决方案的任何帮助表示赞赏,但我很满意我暂时拥有的。谢谢,伙计们。
答案 0 :(得分:0)
这只是来自@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的经验,我无法使用该工作用。
使用它来获得一个简洁的解决方案的任何帮助表示赞赏,但我很满意我暂时拥有的。谢谢,伙计们。
答案 1 :(得分:0)
您的方法有一个限制:结果始终是矩形范围。如果您已复制,请将 A1:B2 和 A4:B5 放入剪贴板,您的方法将返回 A1:B5 ,这意味着行 3 包含在结果范围内,实际上,它不是剪贴板中范围的一部分。 有更多的剪贴板数据类型包含较少的奇怪字符,如 ObjectLink 或链接,但它们对非矩形范围有相同的限制。
在选择范围时按Ctrl键可以选择非矩形范围。