Я использую ASP.Net для вывода данных HTML / XML, чтобы их можно было открыть в MS Excel. Идея, конечно, заключается в том, чтобы иметь возможность отправлять любые табличные данные в Excel. У меня это работает, но я действительно хочу реализовать панель замораживания в верхнем ряду для заголовков столбцов. Из того, что я прочитал, это возможно, и я попытался реализовать биты кода, которые я видел, но все еще без кубиков, и я нашел очень мало хорошего прочтения по этому вопросу.
Вот похожий пост. Я на самом деле реализую предложенный код.
Как заморозить строку заголовка в электронной таблице Excel, экспортированной из ASP.NET
Вот код, используемый для генерации вывода:
Dim html_response As String = ""
html_response &= "<html xmlns:x=""urn:schemas-microsoft-com:office:excel"">" & vbCrLf
html_response &= "<head>" & vbCrLf
html_response &= " <meta http-equiv=""Content-Type"" content=""text/htmlcharset=windows-1252"">" & vbCrLf
html_response &= " <!--[if gte mso 9]>" & vbCrLf
html_response &= " <xml>" & vbCrLf
html_response &= " <x:ExcelWorkbook>" & vbCrLf
html_response &= " <x:ExcelWorksheets>" & vbCrLf
html_response &= " <x:ExcelWorksheet>" & vbCrLf
html_response &= " <x:Name>WorkSheet Name</x:Name>" & vbCrLf
html_response &= " <x:WorksheetOptions>" & vbCrLf
html_response &= " <x:Selected/>" & vbCrLf
html_response &= " <x:FreezePanes/>" & vbCrLf
html_response &= " <x:FrozenNoSplit/>" & vbCrLf
html_response &= " <x:SplitHorizontal>1</SplitHorizontal>" & vbCrLf
html_response &= " <x:TopRowBottomPane>1</TopRowBottomPane>" & vbCrLf
html_response &= " <x:Panes>" & vbCrLf
html_response &= " <x:Pane>" & vbCrLf
html_response &= " <x:Number>3</x:Number>" & vbCrLf
html_response &= " <x:Pane>" & vbCrLf
html_response &= " <x:Pane>" & vbCrLf
html_response &= " <x:Number>2</x:Number>" & vbCrLf
html_response &= " <x:Pane>" & vbCrLf
html_response &= " </x:Panes>" & vbCrLf
html_response &= " <x:ActivePane>2</x:ActivePane>" & vbCrLf
html_response &= " <x:ProtectContents>False</x:ProtectContents>" & vbCrLf
html_response &= " <x:ProtectObjects>False</x:ProtectObjects>" & vbCrLf
html_response &= " <x:ProtectScenarios>False</x:ProtectScenarios>" & vbCrLf
html_response &= " </x:WorksheetOptions>" & vbCrLf
html_response &= " </x:ExcelWorksheet>" & vbCrLf
html_response &= " </x:ExcelWorksheets>" & vbCrLf
html_response &= " </x:ExcelWorkbook>" & vbCrLf
html_response &= " </xml>" & vbCrLf
html_response &= " <![endif]-->" & vbCrLf
html_response &= "</head>" & vbCrLf
html_response &= "<body>" & vbCrLf
'Tabular data retrieved from Session var
html_response &= table_data
html_response &= "</body>" & vbCrLf
html_response &= "</html>" & vbCrLf
'Browser/header stuff
Dim filename As String = Session("UserLoggedIn") & "_" & DateTime.Now().ToFileTime() & ".xls"
Response.Clear()
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader("content-disposition", "attachment filename=" & filename)
Response.Write(html_response)
А вот рисунок, показывающий, что я получаю каждый раз в Excel (я использую Excel 2007):
![excel no freeze frame](https://i.stack.imgur.com/0sNkL.jpg)
Как вы можете видеть, Excel потребляет данные, но в верхней части нет области стоп-кадра, и кажется, что некоторые переменные XML WorkSheetOptions печатаются в ячейке A1.
ПРИМЕЧАНИЕ. Я почти не представляю, как панели и их номера влияют на все это, и я ужасно долго нахожусь в поиске документации. Я был бы рад прочитать и узнать, смогу ли я что-нибудь найти.
Есть идеи, что я здесь не так делаю?
РЕДАКТИРОВАТЬ: Думал, что я опубликую то, что наконец решило мою проблему, на случай, если это понадобится какой-то другой бедной душе. Только целый день возился.
Эта первая функция подготавливает окончательный XML к экспорту через Response.Write, который открывается на клиентском компьютере в Excel, если он установлен.
Public Shared Function FormatBasicSpreadsheet(excel_table_data As String, worksheet_name As String) As String
Dim html As String = ""
'The first two lines make sure Windows opens this document with Excel
html &= "<?xml version=""1.0""?>" & vbCrLf
html &= "<?mso-application progid=""Excel.Sheet""?>" & vbCrLf
html &= "<Workbook xmlns=""urn:schemas-microsoft-com:office:spreadsheet""" & vbCrLf
html &= " xmlns:o=""urn:schemas-microsoft-com:office:office""" & vbCrLf
html &= " xmlns:x=""urn:schemas-microsoft-com:office:excel""" & vbCrLf
html &= " xmlns:ss=""urn:schemas-microsoft-com:office:spreadsheet""" & vbCrLf
html &= " xmlns:html=""http://www.w3.org/TR/REC-html40"">" & vbCrLf
'Add styling for rows/cells
html &= "<Styles>" & vbCrLf
html &= " <Style ss:ID=""Default"" ss:Name=""Normal"">" & vbCrLf
html &= " <Alignment ss:Vertical=""Bottom""/>" & vbCrLf
html &= " <Borders/>" & vbCrLf
html &= " <Font ss:FontName=""Calibri"" x:Family=""Swiss"" ss:Size=""11"" ss:Color=""#000000""/>" & vbCrLf
html &= " <Interior/>" & vbCrLf
html &= " <NumberFormat/>" & vbCrLf
html &= " <Protection/>" & vbCrLf
html &= " </Style>" & vbCrLf
html &= " <Style ss:ID=""header_bold"">" & vbCrLf
html &= " <Alignment ss:Vertical=""Bottom"" ss:WrapText=""0""/>" & vbCrLf
html &= " <Font ss:FontName=""Calibri"" x:Family=""Swiss"" ss:Size=""11"" ss:Color=""#000000"" ss:Bold=""1""/>" & vbCrLf
html &= " <Borders>" & vbCrLf
html &= " <Border ss:Position=""Bottom"" ss:LineStyle=""Continuous"" ss:Weight=""1""/>" & vbCrLf
html &= " <Border ss:Position=""Left"" ss:LineStyle=""Continuous"" ss:Weight=""1""/>" & vbCrLf
html &= " <Border ss:Position=""Right"" ss:LineStyle=""Continuous"" ss:Weight=""1""/>" & vbCrLf
html &= " <Border ss:Position=""Top"" ss:LineStyle=""Continuous"" ss:Weight=""1""/>" & vbCrLf
html &= " </Borders>" & vbCrLf
html &= " <Interior ss:Color=""#F2F2F2"" ss:Pattern=""Solid""/>" & vbCrLf
html &= " </Style>" & vbCrLf
html &= " <Style ss:ID=""all_borders"">" & vbCrLf
html &= " <Borders>" & vbCrLf
html &= " <Border ss:Position=""Bottom"" ss:LineStyle=""Continuous"" ss:Weight=""1""/>" & vbCrLf
html &= " <Border ss:Position=""Left"" ss:LineStyle=""Continuous"" ss:Weight=""1""/>" & vbCrLf
html &= " <Border ss:Position=""Right"" ss:LineStyle=""Continuous"" ss:Weight=""1""/>" & vbCrLf
html &= " <Border ss:Position=""Top"" ss:LineStyle=""Continuous"" ss:Weight=""1""/>" & vbCrLf
html &= " </Borders>" & vbCrLf
html &= " <Interior ss:Color=""#F2F2F2"" ss:Pattern=""Solid""/>" & vbCrLf
html &= " </Style>" & vbCrLf
html &= "</Styles>" & vbCrLf
html &= "<Worksheet ss:Name=""" & worksheet_name & """>" & vbCrLf
'Tabular retrieved from Session var
'NOTE: MUST be in proper Excel XML table format.
html &= excel_table_data & vbCrLf
'Worksheet options - freeze panes, etc.
html &= "<WorksheetOptions xmlns=""urn:schemas-microsoft-com:office:excel"">" & vbCrLf
html &= " <Selected/>" & vbCrLf
html &= " <FreezePanes/>" & vbCrLf
html &= " <FrozenNoSplit/>" & vbCrLf
html &= " <SplitHorizontal>1</SplitHorizontal>" & vbCrLf
html &= " <TopRowBottomPane>1</TopRowBottomPane>" & vbCrLf
html &= " <ActivePane>2</ActivePane>" & vbCrLf
html &= " <Panes>" & vbCrLf
html &= " <Pane>" & vbCrLf
html &= " <Number>3</Number>" & vbCrLf
html &= " </Pane>" & vbCrLf
html &= " <Pane>" & vbCrLf
html &= " <Number>2</Number>" & vbCrLf
html &= " <ActiveRow>0</ActiveRow>" & vbCrLf
html &= " </Pane>" & vbCrLf
html &= " </Panes>" & vbCrLf
html &= " <ProtectObjects>False</ProtectObjects>" & vbCrLf
html &= " <ProtectScenarios>False</ProtectScenarios>" & vbCrLf
html &= "</WorksheetOptions>" & vbCrLf
html &= "</Worksheet>" & vbCrLf
html &= "</Workbook>" & vbCrLf
Return html
Функция завершения
Надеюсь, это может помочь кому-то в будущем. Приветствия.
Вот функция для форматирования данных таблицы Excel XML, результат которой передается в вышеуказанную функцию.
Public Shared Function CreateExcelXmlTableFromSQL(ByVal SQL As String, IncludeHeaderStyling As Boolean) As String
Dim html As String = ""
'These variables are for setting the column width declarations
Dim column_width_template As String = "<Column ss:Width=""$$$""/>"
Dim column_character_pixel_constant As Single = 5.5 'Pixels per character
Dim column_list As New Generic.Dictionary(Of Int32, Int32)
'Open dbase connection
Dim conn As SqlConnection = dbase.CreateSqlConnection()
'Fill the datareader
Dim dr As SqlDataReader = dbase.ReturnDataReader(conn, Sql)
'Check the datareader
If (dr Is Nothing) OrElse (dr.IsClosed) Then
Return ""
End If
'Begin the table
html &= "<Table>" & vbCrLf
'Put columns placeholder in
html &= "[COLUMNS]" & vbCrLf
'NOTE: The datareader object (unlike the old ADODB recordset) is forward only. This means
' means that there is no reset of the pointer. When you read the first row to get
' the column names, you MUST also generate the first row of content, or you'll be missing
' one row.
'Read the first row of the datareader for the column headings, PLUS the first row of data.
While (dr.Read)
'Write table headers
'NOTE: This contains XML style tags
Dim header_row_style As String = " ss:StyleID=""all_borders"""
Dim header_cell_style = " ss:StyleID=""header_bold"""
If (Not IncludeHeaderStyling) Then
header_row_style = ""
header_cell_style = ""
End If
html &= "<Row" & header_row_style & ">" & vbCrLf
For i As Int16 = 0 To dr.FieldCount - 1
'NOTE: you see the styleID I included here. In billing_export_report where I
'build the overall Excel XML doc, I define this.
html &= "<Cell" & header_cell_style & "><Data ss:Type=""String""> " & dr.GetName(i) & "</Data></Cell>" & vbCrLf
column_list.Add(i, dr.GetName(i).Length)
Next
html &= "</Row>" & vbCrLf
'Write the first row of data
html &= "<Row>" & vbCrLf
For i As Int16 = 0 To dr.FieldCount - 1
html &= "<Cell><Data ss:Type=""String""> " & dr(i).ToString() & "</Data></Cell>" & vbCrLf
If (column_list.Item(i) < dr(i).ToString().Length) Then
column_list.Item(i) = dr(i).ToString().Length
End If
Next
html &= "</Row>" & vbCrLf
'Exit this loop after first row
Exit While
End While
'Write the content, starting at the second row, switching row colors.
While (dr.Read)
'Start row
html &= "<Row>" & vbCrLf
'Write the row contents
For i As Int16 = 0 To dr.FieldCount - 1
html &= "<Cell><Data ss:Type=""String""> " & dr(i) & "</Data></Cell>" & vbCrLf
If (column_list.Item(i) < dr(i).ToString().Length) Then
column_list.Item(i) = dr(i).ToString().Length
End If
Next
html &= "</Row>" & vbCrLf
End While
html &= "</Table>" & vbCrLf
'Now put the column declarations in, so that
'the widths are correct.
Dim columns_html As String = ""
For Each k As Generic.KeyValuePair(Of Int32, Int32) In column_list
Dim pixel_value As Single = (k.Value * column_character_pixel_constant) + 10
columns_html &= column_width_template.Replace("$$$", pixel_value.ToString()) & vbCrLf
Next
html = html.Replace("[COLUMNS]", columns_html)
dr.Close()
dr = Nothing
conn.Close()
conn.Dispose()
conn = Nothing
'Return the completed table
Return html
End Function
Вот изображение готового Excel, экспортированного через Response.Write. Вы можете видеть, что у него есть стиль строки заголовка, работает панель замораживания, и ширина столбцов установлена для правильного отображения.
![correct_excel](https://i.stack.imgur.com/SnWYi.jpg)