484 lines
17 KiB
C#
484 lines
17 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.IO;
|
||
using System.Xml.Linq;
|
||
using DocumentFormat.OpenXml.Spreadsheet;
|
||
using DocumentFormat.OpenXml;
|
||
using System.Text.RegularExpressions;
|
||
using System.Data;
|
||
|
||
namespace IronIntel.Contractor
|
||
{
|
||
internal class ChartFormatedData : IOpenXmlExcelStyleAndData
|
||
{
|
||
public ChartFormatedData()
|
||
{
|
||
FormatType = CellFormatType.CSharp;
|
||
}
|
||
|
||
#region IOpenXmlExcelStyleAndData Members
|
||
|
||
public CellAlignment CAlignment { get; set; }
|
||
|
||
public CellBorder CBorder { get; set; }
|
||
|
||
public CellFill CFill { get; set; }
|
||
|
||
public CellFont CFont { get; set; }
|
||
|
||
public CellDataType DataType { get; set; }
|
||
|
||
public string FormatCode { get; set; }
|
||
|
||
public CellFormatType FormatType { get; set; }
|
||
|
||
public object Value { get; set; }
|
||
|
||
public String MergedCellsPosition { get; set; }
|
||
|
||
#endregion
|
||
}
|
||
|
||
public class ExportToExcel
|
||
{
|
||
/// <summary>
|
||
/// 将DataTable的数据导出到Excel
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public byte[] CreateExcel(DataTable data, string caption, double[] columnWidths, string[] MergeTitles)
|
||
{
|
||
COpenXmlExcelSheet osheet = ConvertToOpenXmlObject(data, caption, columnWidths, MergeTitles);
|
||
|
||
MemoryStream ms = null;
|
||
try
|
||
{
|
||
ms = new MemoryStream();
|
||
ExcelXlsx xls = new ExcelXlsx();
|
||
xls.CreatePackage(ms, osheet);
|
||
ms.Position = 0;
|
||
|
||
byte[] bts = new byte[ms.Length];
|
||
int offset = 0;
|
||
while (offset < bts.Length)
|
||
{
|
||
offset += ms.Read(bts, offset, bts.Length - offset);
|
||
}
|
||
|
||
return bts;
|
||
}
|
||
catch { }
|
||
finally
|
||
{
|
||
if (ms != null)
|
||
ms.Close();
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private object ConvertIvalidChars(object s)
|
||
{
|
||
if (s == null) return null;
|
||
if (s.GetType() != typeof(string)) return s;
|
||
const string invalidCharsMatch =
|
||
"(?ims)[\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf" +
|
||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f]";
|
||
|
||
//取代其中無效字元, 通通換成空字串
|
||
s = Regex.Replace(
|
||
s.ToString(),
|
||
invalidCharsMatch, "");
|
||
|
||
return s;
|
||
}
|
||
|
||
private COpenXmlExcelSheet ConvertToOpenXmlObject(DataTable data, string caption, double[] columnWidths, string[] MergeTitles)
|
||
{
|
||
try
|
||
{
|
||
COpenXmlExcelSheet osheet = new COpenXmlExcelSheet();
|
||
|
||
// 设置数据和格式。
|
||
|
||
//所有数据和格式存放在此结构中。
|
||
List<List<IOpenXmlExcelStyleAndData>> dataMatrix = new List<List<IOpenXmlExcelStyleAndData>>();
|
||
osheet.DataMatrix = dataMatrix;
|
||
|
||
//行数据临时对象。
|
||
List<IOpenXmlExcelStyleAndData> rowData = null;
|
||
//单元格数据临时对象。
|
||
ChartFormatedData cellData = null;
|
||
|
||
DataRow rdr = null;
|
||
DataColumn rdc = null;
|
||
|
||
#region 设置宽度。
|
||
|
||
foreach (var w in columnWidths)
|
||
{
|
||
osheet.WidthList.Add(w);
|
||
}
|
||
//for (int k = 0; k < dataFromClient.Columns.Count; k++)
|
||
//{
|
||
// try
|
||
// {
|
||
// rdc = dataFromClient.Columns[k];
|
||
// if (rdc.Attributes == null || !rdc.Attributes.ContainsKey("Width"))
|
||
// {
|
||
// osheet.WidthList.Add(100);
|
||
// }
|
||
// else
|
||
// {
|
||
// osheet.WidthList.Add(Convert.ToDouble(rdc.Attributes["Width"]));
|
||
// }
|
||
// }
|
||
// catch
|
||
// {
|
||
// }
|
||
//}
|
||
|
||
#endregion
|
||
|
||
int rowIndex = 0;
|
||
|
||
#region caption
|
||
|
||
if (!string.IsNullOrEmpty(caption))
|
||
{
|
||
rowData = new List<IOpenXmlExcelStyleAndData>();
|
||
cellData = new ChartFormatedData();
|
||
cellData.CAlignment = new CellAlignment();
|
||
cellData.CAlignment.Align = GetAlignment("center");
|
||
cellData.DataType = CellDataType.String;
|
||
cellData.FormatCode = "";
|
||
|
||
cellData.CFont = new CellFont();
|
||
cellData.CFont.FontSize = 14;
|
||
|
||
cellData.Value = caption;
|
||
cellData.MergedCellsPosition = "A1:" + ConvertColNumber(data.Columns.Count) + "1";
|
||
|
||
rowData.Add(cellData);
|
||
rowIndex += 1;
|
||
dataMatrix.Add(rowData);
|
||
|
||
//设置第一行的高度。
|
||
osheet.RowHeightList.Add(rowIndex, 23);
|
||
|
||
//添加一个空行。
|
||
rowData = new List<IOpenXmlExcelStyleAndData>();
|
||
cellData = new ChartFormatedData();
|
||
cellData.MergedCellsPosition = "A2:" + ConvertColNumber(data.Columns.Count) + "2";
|
||
rowData.Add(cellData);
|
||
rowIndex += 1;
|
||
dataMatrix.Add(rowData);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region MergeTitles
|
||
|
||
if (MergeTitles != null && MergeTitles.Length % 2 == 0)
|
||
{
|
||
rowData = new List<IOpenXmlExcelStyleAndData>();
|
||
|
||
for (int q = 0; q < data.Columns.Count; q++)
|
||
{
|
||
cellData = new ChartFormatedData();
|
||
cellData.CAlignment = new CellAlignment();
|
||
cellData.CAlignment.Align = GetAlignment("center");
|
||
cellData.DataType = CellDataType.String;
|
||
cellData.FormatCode = "";
|
||
|
||
cellData.CFont = new CellFont();
|
||
cellData.CFont.FontSize = 14;
|
||
|
||
rowData.Add(cellData);
|
||
}
|
||
|
||
for (int i = 0; i < MergeTitles.Length; i += 2)
|
||
{
|
||
string[] tmp = MergeTitles[i + 1].Split('-');
|
||
if (tmp.Length == 1) continue;
|
||
|
||
cellData = (ChartFormatedData)rowData[(Convert.ToInt32(tmp[0]) - 1)];
|
||
cellData.Value = MergeTitles[i];
|
||
cellData.MergedCellsPosition = ConvertColNumber(Convert.ToInt32(tmp[0])) + "3:" + ConvertColNumber(Convert.ToInt32(tmp[1])) + "3";
|
||
}
|
||
|
||
rowIndex += 1;
|
||
dataMatrix.Add(rowData);
|
||
//设置第一行的高度。
|
||
osheet.RowHeightList.Add(rowIndex, 15);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region header。
|
||
|
||
rowData = new List<IOpenXmlExcelStyleAndData>();
|
||
|
||
for (int q = 0; q < data.Columns.Count; q++)
|
||
{
|
||
rdc = data.Columns[q];
|
||
cellData = new ChartFormatedData();
|
||
|
||
string alignment = "";
|
||
if (rdc != null)
|
||
{
|
||
//if (rdc.Attributes != null && rdc.Attributes.ContainsKey("Alignment"))
|
||
//{
|
||
// alignment = rdc.Attributes["Alignment"];
|
||
//}
|
||
|
||
cellData.CAlignment = new CellAlignment();
|
||
cellData.CAlignment.Align = GetAlignment(alignment);
|
||
|
||
cellData.CFont = new CellFont();
|
||
cellData.CFont.IsBold = true;
|
||
|
||
cellData.CFill = new CellFill();
|
||
cellData.CFill.FillColor = System.Drawing.Color.Gray;
|
||
|
||
cellData.DataType = CellDataType.String;
|
||
cellData.FormatCode = "";
|
||
}
|
||
|
||
cellData.Value = rdc.ColumnName;
|
||
|
||
rowData.Add(cellData);
|
||
}
|
||
rowIndex += 1;
|
||
osheet.RowHeightList.Add(rowIndex, 18);
|
||
dataMatrix.Add(rowData);
|
||
|
||
#endregion
|
||
|
||
#region real data 。
|
||
|
||
for (int k = 0; k <= data.Rows.Count - 1; k++)
|
||
{
|
||
rdr = data.Rows[k];
|
||
rowData = new List<IOpenXmlExcelStyleAndData>();
|
||
|
||
for (int q = 0; q < data.Columns.Count; q++)
|
||
{
|
||
rdc = data.Columns[q];
|
||
|
||
string format = "";
|
||
//if (rdc != null)
|
||
//{
|
||
//if (rdc.Attributes != null && rdc.Attributes.ContainsKey("DataFormat"))
|
||
//{
|
||
// format = (rdc.Attributes["DataFormat"] == null
|
||
// ? ""
|
||
// : rdc.Attributes["DataFormat"].ToString());
|
||
//}
|
||
//}
|
||
|
||
cellData = new ChartFormatedData();
|
||
|
||
//将特殊格式值处理成字符串显示。
|
||
if (rdr != null)
|
||
{
|
||
bool isProcessed = false;
|
||
cellData.Value =
|
||
ConvertIvalidChars(
|
||
ProcessSpecialFormat(rdr[q], format, ref isProcessed));
|
||
if (isProcessed) format = "";
|
||
}
|
||
cellData.FormatCode = ProcessFormat(format);
|
||
cellData.DataType =
|
||
GetDataType((cellData.Value == null ? typeof(string) : cellData.Value.GetType()));
|
||
|
||
string alignment = "";
|
||
if (rdc != null)
|
||
{
|
||
//if (rdc.Attributes != null && rdc.Attributes.ContainsKey("Alignment"))
|
||
//{
|
||
// alignment = rdc.Attributes["Alignment"];
|
||
//}
|
||
cellData.CAlignment = new CellAlignment();
|
||
cellData.CAlignment.Align = GetAlignment(alignment);
|
||
}
|
||
|
||
//如果是合计行则以浅灰色显示。
|
||
//if (hasTotalRow && k == dataFromClient.Rows.Count - 1)
|
||
//{
|
||
// cellData.CFill = new CellFill();
|
||
// cellData.CFill.FillColor = System.Drawing.Color.LightGray;
|
||
//}
|
||
|
||
//如果是合计列则以浅灰色显示。
|
||
//if (hasTotalColumn && q == dataFromClient.Columns.Count - 1)
|
||
//{
|
||
// cellData.CFill = new CellFill();
|
||
// cellData.CFill.FillColor = System.Drawing.Color.LightGray;
|
||
//}
|
||
|
||
rowData.Add(cellData);
|
||
}
|
||
|
||
//rowIndex += 1;
|
||
//if (hasTotalRow && k == dataFromClient.Rows.Count - 1)
|
||
//{
|
||
// osheet.RowHeightList.Add(rowIndex, totalRowHeight);
|
||
//}
|
||
//else
|
||
//{
|
||
// osheet.RowHeightList.Add(rowIndex, 18);
|
||
//}
|
||
|
||
dataMatrix.Add(rowData);
|
||
}
|
||
|
||
#endregion
|
||
|
||
return osheet;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw ex;
|
||
}
|
||
}
|
||
|
||
private string ConvertColNumber(int colnum)
|
||
{
|
||
string zzz = "Z+";
|
||
Regex reg = new Regex(zzz);
|
||
string result = "";
|
||
MatchCollection mc = null;
|
||
for (int k = 0; k < colnum; k++)
|
||
{
|
||
mc = reg.Matches(result);
|
||
if (mc.Count > 0)
|
||
{
|
||
//是zzz格式。
|
||
string first = result.Substring(0, mc[0].Index);
|
||
if (string.IsNullOrEmpty(first))
|
||
{
|
||
result = result.Replace("Z", "A") + "A";
|
||
}
|
||
else
|
||
{
|
||
char c = first[first.Length - 1];
|
||
c = Convert.ToChar(c + 1);
|
||
result = c.ToString() + result.Substring(mc[0].Index).Replace("Z", "A");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (string.IsNullOrEmpty(result))
|
||
{
|
||
result = "A";
|
||
}
|
||
else
|
||
{
|
||
char c = result[result.Length - 1];
|
||
c = Convert.ToChar(c + 1);
|
||
result = result.Substring(0, result.Length - 1) + c.ToString();
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
private Alignment GetAlignment(string align)
|
||
{
|
||
Alignment horizon = new Alignment() { Horizontal = HorizontalAlignmentValues.Left, WrapText = true };
|
||
|
||
if (string.Equals(align, "center", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
horizon = new Alignment() { Horizontal = HorizontalAlignmentValues.Center, WrapText = true };
|
||
}
|
||
else if (string.Equals(align, "right", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
horizon = new Alignment() { Horizontal = HorizontalAlignmentValues.Right, WrapText = true };
|
||
}
|
||
|
||
return horizon;
|
||
}
|
||
|
||
private CellDataType GetDataType(Type typ)
|
||
{
|
||
CellDataType result = CellDataType.String;
|
||
|
||
switch (Type.GetTypeCode(typ))
|
||
{
|
||
case TypeCode.Int16:
|
||
case TypeCode.Int32:
|
||
case TypeCode.Int64:
|
||
case TypeCode.UInt16:
|
||
case TypeCode.UInt32:
|
||
case TypeCode.UInt64:
|
||
result = CellDataType.Integer;
|
||
break;
|
||
case TypeCode.Decimal:
|
||
case TypeCode.Double:
|
||
case TypeCode.Single:
|
||
result = CellDataType.Float;
|
||
break;
|
||
case TypeCode.DateTime:
|
||
result = CellDataType.Date;
|
||
break;
|
||
case TypeCode.Boolean:
|
||
result = CellDataType.Bool;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private object ProcessSpecialFormat(object val, string format, ref bool isProcessed)
|
||
{
|
||
object result = val;
|
||
isProcessed = false;
|
||
if (val == null || string.IsNullOrEmpty(format.Trim())) return result;
|
||
|
||
CellDataType typ = GetDataType(result.GetType());
|
||
|
||
//第一个特殊格式:如果值是6位字符串,格式是"MMM-yyyy",则按日期处理。
|
||
if (typ == CellDataType.String && string.Equals(format.Replace(" ", ""), "{0:MMM-yyyy}"))
|
||
{
|
||
string str = result.ToString();
|
||
if (str.Length == 6)
|
||
{
|
||
try
|
||
{
|
||
result = new DateTime(Convert.ToInt32(str.Substring(0, 4)), Convert.ToInt32(str.Substring(4)), 1);
|
||
result = string.Format(format, result);
|
||
isProcessed = true;
|
||
}
|
||
catch { }
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
/// <summary>
|
||
/// 处理Format格式,使一些特殊符号(如:*、@)可以直接在Excel中看到,而不是解释成Excel中对这些符号的定义
|
||
/// </summary>
|
||
/// <param name="format">格式字符串</param>
|
||
/// <returns></returns>
|
||
private string ProcessFormat(string format)
|
||
{
|
||
string resultFormat = format;
|
||
if (string.IsNullOrEmpty(resultFormat)) return resultFormat;
|
||
if (format.IndexOf("*") >= 0)
|
||
{
|
||
resultFormat = resultFormat.Replace("*", "\"*\"");
|
||
}
|
||
if (format.IndexOf("@") >= 0)
|
||
{
|
||
resultFormat = resultFormat.Replace("@", "\"@\"");
|
||
}
|
||
return resultFormat;
|
||
}
|
||
}
|
||
}
|