484 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}