日前公司要求实现将data table中的数据转换成Excel文件格式提供给用户下载,几经周折,试过很多中方法,终于找到一个相对比较好的解决方案,虽然不够漂亮,但是基本上实现了这个需求。
1 。安装。Net3.0 ,下载 Openxml.dll
这些都是可以从微软的网站上免费获得。
2。可以做使用Excel2007做一个模板,设置好style,这样可以很方便。如果自己生成新的Excel文件的话,也可以,不过要深入研究OpenXml的格式。
3。具体的转换代码(需要改动
4。在具体的使用中,使用stream的方式提供给用户下载。代码如下:
(1)调用代码
DataTable dt = .........
string parentFolderPath = Server.MapPath("Excel");
if (dt == null) return;
ORE.BusinessLogic.TransferToExcel transfer = new ORE.BusinessLogic.TransferToExcel();
byte[] results = transfer.TransferToOpenXMLExcelByStream(parentFolderPath, dt, ViewState["Option"].ToString());
if (results != null)
{
Response.ClearContent();
Response.ContentType = "application/x-zip-compressed"; //this is very important
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.AddHeader("Content-Disposition", "attachment;filename=" + LabelTitle.Text.Replace(" ", "") + ".xlsx");
Response.BinaryWrite(results);
Response.Flush();
Response.Close();
}
else
{
string errorMessage = "Transfer process terminated unexpectedly, please contact the ORE Helpdesk";
Response.Write("<script language='javascript'>alert('" + errorMessage + "');</script>");
}
(2) transferring code
using System;
using System.Data;
using System.Configuration;
using System.Web;
using Microsoft.Office.DocumentFormat.OpenXml.Packaging;
using System.IO.Packaging;
using System.IO;
using System.Data.SqlClient;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Text;
/// <summary>
/// Transfer the data to the OpenXML Excel format
/// Added by zhailei 2007-12-24
/// needs to add WindowsBase and OpenXml references
/// </summary>
struct OutputColumn
{
private string _colName;
private string _outputColName;
private int _outputColWidth;
public string ColumnName
{
get
{
return _colName;
}
}
public string OutputColumnName
{
get
{
return _outputColName;
}
}
public int OutputColWidth
{
get
{
return _outputColWidth;
}
}
public OutputColumn(string colName, string outputColName):this(colName,outputColName,10)
{
}
public OutputColumn(string colName, string outputColName, int outputColWidth)
{
this._colName = colName;
this._outputColName = outputColName;
this._outputColWidth = outputColWidth;
}
}
public class TransferToExcel
{
public byte[] TransferToOpenXMLExcelByStream(string parentFolderPath, DataTable data,string option)
{
//template file
string filePath = parentFolderPath + @"/template.xlsx";
FileInfo file = new FileInfo(filePath);
if (!file.Exists)
{
return null;
}
//read the template file to a byte[] buffer
byte[] srcFileBuffer;
using (FileStream srcFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
srcFileBuffer = new byte[srcFileStream.Length];
srcFileStream.Read(srcFileBuffer, 0, (int)srcFileStream.Length);
}
byte[] resultFileBuffer;
using (MemoryStream workStream = new MemoryStream())
{
workStream.Write(srcFileBuffer, 0, srcFileBuffer.Length);
if (OpenXlsDocumentByStream(workStream, data,option) == true)
{
resultFileBuffer = new byte[workStream.Length];
workStream.Seek(0, SeekOrigin.Begin);
workStream.Read(resultFileBuffer, 0, (int)workStream.Length);
return resultFileBuffer;
}
else
return null;
}
}
private bool OpenXlsDocumentByStream(MemoryStream workStream, DataTable data,string option)
{
try
{
using (SpreadsheetDocument xlDoc = SpreadsheetDocument.Open(workStream, true))
{
if (xlDoc == null) return false;
//find fromOre sheet
const string worksheetNamespace = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
XmlDocument doc = new XmlDocument();
doc.Load(xlDoc.WorkbookPart.GetStream());
XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("d", doc.DocumentElement.NamespaceURI);
nsManager.AddNamespace("w", worksheetNamespace);
string searchString = string.Format("//d:sheet[@name='{0}']", "FromORE"); //FromORE is according to the template file
XmlNode sheetNode = doc.SelectSingleNode(searchString, nsManager);
if (sheetNode == null) return false;
// Get the relationship id attribute:
XmlAttribute relationAttribute = sheetNode.Attributes["r:id"];
if (relationAttribute == null) return false;
string relId = relationAttribute.Value;
// loads its contents as XML:
WorksheetPart worksheetPart = (WorksheetPart)xlDoc.WorkbookPart.GetPartById(relId);
if (InsertNewData(worksheetPart, data, nsManager,option) == true)
{
doc.Save(xlDoc.WorkbookPart.GetStream(FileMode.Create));
return true;
}
else
return false;
}
}
catch
{
return false;
}
}
private bool InsertNewData(WorksheetPart part, DataTable data, XmlNamespaceManager nsManager,string option)
{
XmlDocument sheetDoc = new XmlDocument();
sheetDoc.Load(part.GetStream());
// Get the columns' name of output columns
OutputColumn[] outputColumns = GetOutputColumns(option);
string worksheetNamespace = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
//set the columns' width
XmlNode sheetCols = sheetDoc.SelectSingleNode("//w:cols", nsManager);
if (sheetCols == null) return false;
int colIndex;
for (int i = 0; i < outputColumns.Length; i++)
{
colIndex = i + 1;
string xpath = @"./w:col[@min='" + colIndex.ToString() + "']";
XmlNode colNode = sheetCols.SelectSingleNode(xpath, nsManager);
if (colNode != null)
{
colNode.Attributes["width"].Value = outputColumns[i].OutputColWidth.ToString();
}
else
{
XmlNode newColNode = sheetDoc.CreateElement("col", worksheetNamespace);
colIndex = i + 1;
newColNode.Attributes.Append(sheetDoc.CreateAttribute("min"));
newColNode.Attributes["min"].Value = colIndex.ToString();
newColNode.Attributes.Append(sheetDoc.CreateAttribute("max"));
newColNode.Attributes["max"].Value = colIndex.ToString();
newColNode.Attributes.Append(sheetDoc.CreateAttribute("style"));
newColNode.Attributes["style"].Value = "1";
newColNode.Attributes.Append(sheetDoc.CreateAttribute("width"));
newColNode.Attributes["width"].Value = outputColumns[i].OutputColWidth.ToString();
newColNode.Attributes.Append(sheetDoc.CreateAttribute("bestFit"));
newColNode.Attributes["bestFit"].Value = "1";
newColNode.Attributes.Append(sheetDoc.CreateAttribute("customWidth"));
newColNode.Attributes["customWidth"].Value = "1";
sheetCols.AppendChild(newColNode);
}
}
//Get the sheetData node
XmlNode sheetDataNode = sheetDoc.SelectSingleNode("//w:sheetData", nsManager);
//sheetDataNode is not found
if (sheetDataNode == null)
return false;
// Columns' Name in row 1
XmlNode ColRowNode = sheetDoc.CreateElement("row", worksheetNamespace);
ColRowNode.Attributes.Append(sheetDoc.CreateAttribute("r"));
ColRowNode.Attributes["r"].Value = "1";
ColRowNode.Attributes.Append(sheetDoc.CreateAttribute("s"));
ColRowNode.Attributes["s"].Value = "2";
for (int col = 0; col < outputColumns.Length; col++)
{
//create a new cell node
XmlNode newCellNode = sheetDoc.CreateElement("c", worksheetNamespace);
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("s"));
newCellNode.Attributes["s"].Value = "5"; //titel style
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("t"));
newCellNode.Attributes["t"].Value = "inlineStr";
// set the cell value
XmlNode newCellValueNode = sheetDoc.CreateElement("is", worksheetNamespace);
XmlNode newCellValueNode1 = sheetDoc.CreateElement("t", worksheetNamespace);
newCellValueNode1.InnerText = outputColumns[col].OutputColumnName;
//set the relations of all the created nodes
newCellValueNode.AppendChild(newCellValueNode1);
newCellNode.AppendChild(newCellValueNode);
ColRowNode.AppendChild(newCellNode);
}
sheetDataNode.AppendChild(ColRowNode);
//insert the data from row 2
for (int row = 0; row < data.Rows.Count; row++)
{
XmlNode newRowNode = sheetDoc.CreateElement("row", worksheetNamespace);
for (int col = 0; col < outputColumns.Length; col++)
{
XmlNode newCellNode = sheetDoc.CreateElement("c", worksheetNamespace);
XmlNode newCellValueNode;
XmlNode newCellValueNode1;
switch (outputColumns[col].OutputColumnName)
{
case "ORE ID":
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("s"));
newCellNode.Attributes["s"].Value = "6"; //normal style
newCellValueNode = sheetDoc.CreateElement("v", worksheetNamespace);
newCellValueNode.InnerText = (data.Rows[row][outputColumns[col].ColumnName] == null) ? "" : data.Rows[row][outputColumns[col].ColumnName].ToString();
newCellNode.AppendChild(newCellValueNode);
newRowNode.AppendChild(newCellNode);
break;
case "Product Revenue":
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("s"));
newCellNode.Attributes["s"].Value = "4";// currency style
newCellValueNode = sheetDoc.CreateElement("v", worksheetNamespace);
if (data.Rows[row][outputColumns[col].ColumnName] != null)
{
decimal temp = (decimal)data.Rows[row][outputColumns[col].ColumnName];
newCellValueNode.InnerText = temp.ToString("F0");
}
else
{
newCellValueNode.InnerText = "0";
}
newCellNode.AppendChild(newCellValueNode);
newRowNode.AppendChild(newCellNode);
break;
case "Create Date":
case "Requested Start Date":
case "Oppty Due Date":
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("s"));
newCellNode.Attributes["s"].Value = "2"; //date style
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("t"));
newCellNode.Attributes["t"].Value = "inlineStr";
newCellValueNode = sheetDoc.CreateElement("is", worksheetNamespace);
newCellValueNode1 = sheetDoc.CreateElement("t", worksheetNamespace);
if (data.Rows[row][outputColumns[col].ColumnName] == null)
{
newCellValueNode1.InnerText = "";
}
else
{
DateTime temp = (DateTime)data.Rows[row][outputColumns[col].ColumnName];
newCellValueNode1.InnerText = temp.ToString("MM/dd/yyyy");
}
newCellValueNode.AppendChild(newCellValueNode1);
newCellNode.AppendChild(newCellValueNode);
newRowNode.AppendChild(newCellNode);
break;
case "Notes":
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("s"));
newCellNode.Attributes["s"].Value = "3";//with wrapText style
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("t"));
newCellNode.Attributes["t"].Value = "inlineStr";
newCellValueNode = sheetDoc.CreateElement("is", worksheetNamespace);
newCellValueNode1 = sheetDoc.CreateElement("t", worksheetNamespace);
newCellValueNode1.InnerText = (data.Rows[row][outputColumns[col].ColumnName] == null) ? "" : data.Rows[row][outputColumns[col].ColumnName].ToString();
//set the relations of all the created nodes
newCellValueNode.AppendChild(newCellValueNode1);
newCellNode.AppendChild(newCellValueNode);
newRowNode.AppendChild(newCellNode);
break;
default:
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("s"));
newCellNode.Attributes["s"].Value = "6";
newCellNode.Attributes.Append(sheetDoc.CreateAttribute("t"));
newCellNode.Attributes["t"].Value = "inlineStr";
newCellValueNode = sheetDoc.CreateElement("is", worksheetNamespace);
newCellValueNode1 = sheetDoc.CreateElement("t", worksheetNamespace);
newCellValueNode1.InnerText = (data.Rows[row][outputColumns[col].ColumnName] == null) ? "" : data.Rows[row][outputColumns[col].ColumnName].ToString();
//set the relations of all the created nodes
newCellValueNode.AppendChild(newCellValueNode1);
newCellNode.AppendChild(newCellValueNode);
newRowNode.AppendChild(newCellNode);
break;
}
}
sheetDataNode.AppendChild(newRowNode);
}
// Save the worksheet part.
Stream st = part.GetStream(FileMode.Create);
sheetDoc.Save(st);
return true;
}
/// <summary>
/// get the index of outputting columns
/// </summary>
private OutputColumn[] GetOutputColumns(string option)
{
int num;
switch (option)
{
case "ViewByTST":
case "ViewByTeamSpecialist":
num = 21;
break;
default :
num = 19;
break;
}
OutputColumn[] outputColumns = new OutputColumn[num];
outputColumns[0] = new OutputColumn("OppID", "ORE ID",8);
outputColumns[1] = new OutputColumn("SiebelID", "Oppty ID",10);
outputColumns[2] = new OutputColumn("Status", "Status",10);
outputColumns[3] = new OutputColumn("RequestName", "Request Name",20);
outputColumns[4] = new OutputColumn("Company", "Company",20);
outputColumns[5] = new OutputColumn("Segment", "Segment",20);
outputColumns[6] = new OutputColumn("STUTeamName", "Team",20);
outputColumns[7] = new OutputColumn("PreSalesOffering", "Activity",30);
outputColumns[8] = new OutputColumn("SiebelWorkloadType", "Primary Workload Type",20);
outputColumns[9] = new OutputColumn("SiebelWorkloadDetail", "Primary Workload Detail",20);
outputColumns[10] = new OutputColumn("SiebelProductRevenue", "Product Revenue");
outputColumns[11] = new OutputColumn("SiebelDueDate", "Oppty Due Date");
outputColumns[12] = new OutputColumn("SiebelSalesStage", "Sales Stage Request");
outputColumns[13] = new OutputColumn("CurrencySalesStage", "Sales Stage Current",15);
outputColumns[14] = new OutputColumn("Impact", "Sales Stage Change"); //This column has condition format,so if adapted the order of the column,the template.xlsx need to be adjusted too
outputColumns[15] = new OutputColumn("Originator", "Requestor");
outputColumns[16] = new OutputColumn("STUSpecialist", "Specialist",15);
outputColumns[17] = new OutputColumn("CreateDate", "Create Date");
if (num == 19)
outputColumns[18] = new OutputColumn("Notes", "Notes",100);
else
{
outputColumns[18] = new OutputColumn("RequestedStartDate", "Requested Start Date");
outputColumns[19] = new OutputColumn("Duration", "Duration");
outputColumns[20] = new OutputColumn("Notes", "Notes",100);
}
return outputColumns;
}
}