1

これが私が達成したいことです:

ユーザーが 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. Excel 2010 と VS2010 を使用しています - Win7 で 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 の無能さと経験不足のために機能させることができませんでした。

これを使用してきちんとした解決策を得るのに役立つことは大歓迎ですが、当分の間、私が持っているものに満足しています. みんなありがとう。

4

2 に答える 2

0

これは@drdhkからの回答です。これは、これが回答されたことを示すためにコメントの1つで要求されたためです。

そう、

そして、ここまで読んでくれた皆さん、ありがとう。私はついにそれを理解しました。クリップボードからストリームの実際の構造に頭を悩ませることができないため、私の解決策はまだ厄介ですが、探しているものを見つけました:

    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 の無能さと経験不足のために機能させることができませんでした。

これを使用してきちんとした解決策を得るのに役立つことは大歓迎ですが、当分の間、私が持っているものに満足しています. みんなありがとう。

于 2015-10-14T14:39:58.440 に答える
0

このアプローチには 1 つの制限があります。結果は常に長方形の範囲になります。A1:B2A4:B5をクリップボードにコピーした場合、アプローチはA1:B5を返します。これは、行3が結果範囲に含まれていることを意味します。実際には、行 3 は範囲の一部ではありませんでしたクリップボード。ObjectLinkLinkなど、あまり奇妙な文字を含まないクリップボード データ型が他にもありますが、長方形以外の範囲については同じ制限があります。

Ctrl キーを押しながら範囲を選択すると、四角形以外の範囲を選択できます。

于 2016-06-11T11:43:59.773 に答える