Вам нужно использовать другой формат из буфера обмена - XML Spreadsheet
. Скопированные данные содержатся в специальном XML с собственной структурой и атрибутами. Давайте возьмем данные следующего листа:
Как видите, каждая ячейка имеет некоторое форматирование. 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