Получить свойства ячейки Excel, которые были скопированы в буфер обмена - PullRequest
1 голос
/ 03 июля 2019

Я пытаюсь скопировать значения из нескольких ячеек в одну ячейку.Если бы я только хотел объединить значения ячеек, я бы использовал что-то вроде

Dim str as string = My.Computer.ClipBoard.GetText
oxlapp.ActiveCell.Value = str

Однако

В этом случае мне нужно включить html-теги,чтобы создать таблицу, и я также хочу включить форматирование, как жирный, курсив и подчеркнутый.Поэтому вместо простого текста из буфера обмена мне нужно знать некоторые свойства ячеек.

Я знаю, что они должны быть там, потому что вы, конечно, можете копировать / вставлять целые ячейки.

До сих пор я пытался получить ячейки Excel, используя

My.Computer.Clipboard.GetData(XlClipboardFormat.xlClipboardFormatTable)

и

My.Computer.Clipboard.GetData(XlClipboardFormat.xlClipboardFormatCSV)

, но во время отладки я заметил, что оба они вернули Nothing.

Кто-нибудь знает, как я могу получить все свойства ячеек из буфера обмена?

Чтобы сделать это более понятным, я хочу это

enter image description here

Чтобы превратить в это:

enter image description here

Если есть какой-либо другой способ, кроме использования буфера обмена, я был бы радпопробуй.

Ответы [ 2 ]

1 голос
/ 03 июля 2019

Вам нужно использовать другой формат из буфера обмена - XML Spreadsheet. Скопированные данные содержатся в специальном XML с собственной структурой и атрибутами. Давайте возьмем данные следующего листа:

IMG1

Как видите, каждая ячейка имеет некоторое форматирование. XML для этих данных следующий:

<ss:Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
             xmlns:o="urn:schemas-microsoft-com:office:office"
             xmlns:x="urn:schemas-microsoft-com:office:excel"
             xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
             xmlns:html="http://www.w3.org/TR/REC-html40">
    <ss:Styles>
        <ss:Style ss:ID="Default" ss:Name="Normal">
            <ss:Alignment ss:Vertical="Bottom"/>
            <ss:Borders/>
            <ss:Font ss:FontName="Calibri" x:CharSet="204" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
            <ss:Interior/>
            <ss:NumberFormat/>
            <ss:Protection/>
        </ss:Style>
        <ss:Style ss:ID="s62">
            <ss:Interior ss:Color="#FFFF00" ss:Pattern="Solid"/>
        </ss:Style>
        <ss:Style ss:ID="s63">
            <ss:Font ss:FontName="Calibri" x:CharSet="204" x:Family="Swiss" ss:Size="11" ss:Color="#000000" ss:Bold="1"/>
        </ss:Style>
        <ss:Style ss:ID="s64">
            <ss:Font ss:FontName="Calibri" x:CharSet="204" x:Family="Swiss" ss:Size="11" ss:Color="#0000FF"/>
        </ss:Style>
        <ss:Style ss:ID="s65">
            <ss:Font ss:FontName="Calibri" x:CharSet="204" x:Family="Swiss" ss:Size="11" ss:Color="#000000" ss:Italic="1"/>
        </ss:Style>
    </ss:Styles>
    <ss:Worksheet ss:Name="Sheet1">
        <ss:Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="2" ss:DefaultRowHeight="15">
            <ss:Row>
                <ss:Cell ss:StyleID="s62">
                    <ss:Data ss:Type="String">A</ss:Data>
                </ss:Cell>
                <ss:Cell ss:StyleID="s63">
                    <ss:Data ss:Type="String">1</ss:Data>
                </ss:Cell>
            </ss:Row>
            <ss:Row>
                <ss:Cell ss:StyleID="s64">
                    <ss:Data ss:Type="String">B</ss:Data>
                </ss:Cell>
                <ss:Cell ss:StyleID="s65">
                    <ss:Data ss:Type="String">2</ss:Data>
                </ss:Cell>
            </ss:Row>
        </ss:Table>
    </ss:Worksheet>
</ss:Workbook>

Как видите, у вас есть вся информация о форматировании в соответствующих стилях. Для instace значение A в ячейке A1 имеет стиль s62 (атрибут StyleID) - вы можете найти соответствующий узел Style с этим номером в узле Styles. Структура строк и столбцов в этом XML неявна - то есть вы не увидите индексы строк и столбцов - вам нужно рассчитать их самостоятельно. Например, второй Cell узел в первом Row узле - это первая строка, второй столбец .

Следующий код генерирует данные на рисунке выше и извлекает соответствующие элементы для манипуляции.

Предостережение 1. Если присмотреться, узел Workbook имеет two urn:schemas-microsoft-com:office:spreadsheet пространств имен: first по умолчанию, а second с префиксом ss. Просто помните - вам всегда нужно использовать префикс ss!

Предостережение 2. Этот метод имеет один недостаток - он не распознает скрытые строки (вручную или с помощью автофильтра) и столбцы! Он также включает скрытые строки / столбцы!

Imports <xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
Imports <xmlns:x="urn:schemas-microsoft-com:office:excel">

Sub GetCellsWithFormat()
    '// Create new Excel app
    Dim xlApp = New Excel.Application With {.Visible = True}
    Dim book = xlApp.Workbooks.Add()
    Dim sheet = DirectCast(book.Sheets(1), Excel.Worksheet)
    '// Apply some formatting
    With sheet
        .Range("A1").Interior.Color = Excel.XlRgbColor.rgbYellow
        .Range("B1").Font.Bold = True
        .Range("A2").Font.Color = Excel.XlRgbColor.rgbBlue
        .Range("B2").Font.Italic = True
        '// Add some values
        Dim arr = Array.CreateInstance(GetType(String), {2, 2}, {1, 1})
        arr(1, 1) = "A" : arr(1, 2) = "1"
        arr(2, 1) = "B" : arr(2, 2) = "2"
        With .Range("A1:B2")
            .Value = arr
            .Copy() '//Copy cells to clipboard
        End With
        Dim xml As XElement
        Using xml_stream = DirectCast(Clipboard.GetData("XML Spreadsheet"), Stream)
            '// Get rid of last character (new line) to avoid parsing error
            xml_stream.SetLength(xml_stream.Length - 1)
            xml = XElement.Load(xml_stream)
        End Using
        '// Get any element you need
        Dim styles = xml.<ss:Styles>(0)
        Dim table = xml.<ss:Worksheet>.<ss:Table>(0)
        Dim rows = table.<ss:Row>
        '// Do something with this data
    End With
End Sub

UPDATE

На самом деле вам не нужно использовать буфер обмена , чтобы получить этот XML - вам просто нужно использовать xlRangeValueXMLSpreadsheet значение Value свойство:

With sheet
    '// Same code...
    With .Range("A1:B2")
        .Value = arr
        '.Copy() '//No need to copy!
    End With
    Dim xml_string = CStr(.Range("A1:B2").Value(Excel.XlRangeValueDataType.xlRangeValueXMLSpreadsheet))
    '// Again, exclude last character
    Dim xml = XElement.Parse(xml_string.Substring(0, xml_string.Length - 1))
    '// Get any element you need
    Dim styles = xml.<ss:Styles>(0)
    Dim table = xml.<ss:Worksheet>.<ss:Table>(0)
    Dim rows = table.<ss:Row>
    '// Do something with this data
End With
0 голосов
/ 03 июля 2019

Когда я хочу разрешить копирование данных из Excel в пользовательское приложение Windows, которое я написал, я использую GetText () вместо GetData ().

Dim ClipboardText As String = Nothing

   ClipboardText = My.Computer.Clipboard.GetText()

Если в буфер обмена скопированы несколько ячеек из Excel, они могут быть разделены vbTab и vbCrLf в зависимости от выбора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...