You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

437 lines
17 KiB

4 years ago
using System;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using Application = Microsoft.Office.Interop.Excel.Application;
using DataTable = System.Data.DataTable;
namespace CK.SCP.Utils
{
public static class ExcelWriter
{
//ieachsize为每次写行的数值,可以自己设置
private const int EachSize = 5000;
private const int RStartIndex = 1;
private const int CStartIndex = 0;
public static readonly SaveFileDialog SaveFileDialog = new SaveFileDialog
{
Filter = "Excel 工作簿 (*.xlsx)|*.xlsx",
CheckFileExists = false,
CheckPathExists = false,
FilterIndex = 0,
RestoreDirectory = true,
CreatePrompt = false,
Title = "保存为Excel文件"
};
private static void SetWorkSheetValue(Application excel, Worksheet sheet, DataTable dt, string fileName)
{
Range r = null;
var rIdx = RStartIndex;
var cIdx = CStartIndex;
if (!string.IsNullOrEmpty(dt.TableName))
{
sheet.Name = dt.TableName;
}
//
//取得标题
//
foreach (DataColumn dc in dt.Columns)
{
cIdx++;
excel.Cells[rIdx, cIdx] = dc.ColumnName;
//设置标题格式为居中对齐
r = sheet.Range[excel.Cells[rIdx, cIdx], excel.Cells[rIdx, cIdx]];
r.HorizontalAlignment = XlVAlign.xlVAlignCenter;
r.Interior.ColorIndex = 19;
}
//因为第一行已经写了表头,所以所有数据都应该从a2开始
r = sheet.Range[excel.Cells[rIdx, cIdx], excel.Cells[rIdx, cIdx]];
//irowcount为实际行数,最大行
var irowcount = dt.Rows.Count;
int iParstedRow = 0, iCurSize = 0;
//ieachsize为每次写行的数值,可以自己设置
//icolumnaccount为实际列数,最大列数
var iColumnsCount = dt.Columns.Count;
//在内存中声明一个ieachsize×icolumnaccount的数组,ieachsize是每次最大存储的行数,icolumnaccount就是存储的实际列数
var objval = new object[EachSize, iColumnsCount];
iCurSize = EachSize;
while (iParstedRow < irowcount)
{
if ((irowcount - iParstedRow) < EachSize)
iCurSize = irowcount - iParstedRow;
//用for循环给数组赋值
for (var i = 0; i < iCurSize; i++)
{
for (var j = 0; j < iColumnsCount; j++)
{
var s = dt.Rows[i + iParstedRow][j].ToString();
//////////////////
//格式化日期字段
var dc = dt.Columns[j];
if (dc.DataType.FullName == "System.DateTime" && s != null && s != "")
{
DateTime time;
DateTime.TryParse(s, out time);
s = time.ToString();
}
//////////////////
decimal d;
if (decimal.TryParse(s, out d))
{
if (Math.Round(d, 5) == 0)
{
objval[i, j] = string.Empty;
continue;
}
}
objval[i, j] = s;
}
System.Windows.Forms.Application.DoEvents();
}
var X = "A" + (iParstedRow + 2);
var col = "";
if (iColumnsCount <= 26)
{
col = ((char)('A' + iColumnsCount - 1)) +
((iParstedRow + iCurSize + 1)).ToString(CultureInfo.InvariantCulture);
}
else
{
col = ((char)('A' + (iColumnsCount / 26 - 1))) +
((char)('A' + (iColumnsCount % 26 - 1))).ToString() +
((iParstedRow + iCurSize + 1));
}
r = sheet.Range[X, col];
// 调用range的value2属性,把内存中的值赋给excel
r.Value2 = objval;
iParstedRow = iParstedRow + iCurSize;
}
var rSumIdx = dt.Rows.Count + 1;
var cSumIdx = CStartIndex + 1;
// //加载一个合计行
// //
// //excel.Cells[rowSum, 2] = "合计";
//
// r = sheet.Range[excel.Cells[rSumIdx, 2], excel.Cells[rSumIdx, 2]];
// r.HorizontalAlignment = XlVAlign.xlVAlignCenter;
//
// //
//设置选中的部分的颜色
//
r = sheet.Range[excel.Cells[2, cSumIdx], excel.Cells[2, cIdx]];
r.Select();
//设置为浅黄色,共计有56种
// r.Interior.ColorIndex = 19;
//
//设置报表表格为最适应宽度
//
r = sheet.Range[excel.Cells[RStartIndex, cSumIdx], excel.Cells[rSumIdx, cIdx]];
r.Select();
r.Columns.AutoFit();
//
//绘制边框
//
r = sheet.Range[excel.Cells[RStartIndex, cSumIdx], excel.Cells[rSumIdx, cIdx]];
r.Borders.LineStyle = 1;
r = sheet.Range[excel.Cells[RStartIndex, cSumIdx], excel.Cells[rSumIdx, cSumIdx]];
r.Borders[XlBordersIndex.xlEdgeLeft].Weight = XlBorderWeight.xlThick; //设置左边线加粗
r = sheet.Range[excel.Cells[RStartIndex, cSumIdx], excel.Cells[RStartIndex, cIdx]];
r.Borders[XlBordersIndex.xlEdgeTop].Weight = XlBorderWeight.xlThick; //设置上边线加粗
r = sheet.Range[excel.Cells[RStartIndex, cIdx], excel.Cells[rSumIdx, cIdx]];
r.Borders[XlBordersIndex.xlEdgeRight].Weight = XlBorderWeight.xlThick; //设置右边线加粗
r = sheet.Range[excel.Cells[rSumIdx, cSumIdx], excel.Cells[rSumIdx, cIdx]];
r.Borders[XlBordersIndex.xlEdgeBottom].Weight = XlBorderWeight.xlThick; //设置下边线加粗
//r = sheet.Range[excel.Cells[0, 0], null];
//
//显示效果
//
excel.Visible = false;
excel.DisplayAlerts = false;
excel.AlertBeforeOverwriting = false;
}
private static void ReleaseObject(object obj)
{
try
{
Marshal.ReleaseComObject(obj);
obj = null;
}
catch
{
obj = null;
}
finally
{
GC.Collect();
}
}
[DllImport("User32.dll", CharSet = CharSet.Auto)]
private static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
private static void Kill(_Application excel)
{
try
{
var t = new IntPtr(excel.Hwnd);
var k = 0;
GetWindowThreadProcessId(t, out k);
var p = Process.GetProcessById(k);
p.Kill();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
/// <summary>
/// 将DataTable数据写入Excel文件
/// </summary>
/// <param name="dt">DataTable</param>
public static void Write(DataTable dt)
{
if (SaveFileDialog.ShowDialog() == DialogResult.OK)
{
var fileName = SaveFileDialog.FileName;
WriteDataTableToExcel(dt, fileName);
}
}
/// <summary>
/// 将DataTable数据写入Excel文件
/// </summary>
/// <param name="dt">DataTable</param>
/// <param name="fileName">Excel文件路径</param>
public static void Write(DataTable dt, string fileName)
{
try
{
if (string.IsNullOrEmpty(fileName))
{
Write(dt);
}
else
{
WriteDataTableToExcel(dt, fileName);
}
}
catch
{
MessageBox.Show("无法解析文件路径!");
}
}
private static void WriteDataTableToExcel(DataTable dt, string fileName)
{
var fileExt = fileName.Substring(fileName.LastIndexOf('.'));
if (fileExt.ToUpper() == ".XLSX")
{
if (dt != null && dt.Rows.Count > 0)
{
var poDv = new ProcessOperator
{
BackgroundWork = () => WriteExcelByDataTable(dt, fileName)
};
poDv.BackgroundWorkerCompleted += WriteExcel_Completed;
poDv.Start();
}
else
{
MessageBox.Show("当前表单没有任何数据");
}
}
else
{
MessageBox.Show("无法解析该后缀名的文件!");
}
}
// /// <summary>
// /// 将DataSet数据写入Excel文件
// /// </summary>
// /// <param name="dsExcel">DataSet</param>
// public void Write(DataSet dsExcel)
// {
// if (dsExcel != null && dsExcel.Tables.Count > 0)
// {
// if (_saveFileDialog.ShowDialog() == DialogResult.OK)
// {
// string fileName = _saveFileDialog.FileName; //得到存放路径
// var poDv = new ProcessOperator
// {
// MessageInfo = @"正在写入" + Path.GetFileName(fileName) + "文件",
// BackgroundWork = () => WriteExcelByDataSet(dsExcel, fileName)
// };
// poDv.BackgroundWorkerCompleted += WriteExcel_Completed;
// poDv.Start();
// }
// }
// else
// {
// MessageBox.Show("当前没有任何表单!");
// }
// }
public static void Write(DataSet ds)
{
if (SaveFileDialog.ShowDialog() == DialogResult.OK)
{
var fileName = SaveFileDialog.FileName;
Write(ds, fileName);
}
}
public static void Write(DataSet dsExcel, string fileName)
{
try
{
// if (string.IsNullOrEmpty(fileName))
// {
// Write(dsExcel);
// }
// else
// {
if (dsExcel != null && dsExcel.Tables.Count > 0)
{
if (File.Exists(fileName))
File.Delete(fileName);
//_saveFileDialog.FileName = fileName;
//if (_saveFileDialog.ShowDialog() == DialogResult.OK)
{
//_writeSheetName = new List<string>();
foreach (DataTable dt in dsExcel.Tables)
{
if (dt == null || dt.TableName == null || dt.TableName == "") continue;
ExcelReader.RemoveEmptyRow(dt);
//string name = _saveFileDialog.FileName;
var dt1 = dt;
var poDv = new ProcessOperator
{
MessageInfo = @"正在写入" + Path.GetFileName(fileName) + "," + dt.TableName,
BackgroundWork = () => WriteExcelByDataTable(dt1, fileName)
};
poDv.Start();
}
WriteExcel_Completed(null, null);
}
}
else
{
MessageBox.Show("当前没有任何表单!");
}
// }
}
catch (Exception ex)
{
MessageBox.Show("无法解析文件路径!\n" + ex);
}
}
public static void WriteExcelByDataTable(DataTable dt, string fileName)
{
// if (_writeSheetName == null)
// {
// _writeSheetName = new List<string>();
// }
Workbook workbook = null;
Worksheet sheet = null;
var excel = new Application();
var miss = Missing.Value;
try
{
if (File.Exists(fileName))
{
workbook = excel.Workbooks.Open(fileName, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true,
false, 0, true, false, false);
var sheets = workbook.Sheets;
var existSheetName = string.Empty;
for (var i = 1; i <= sheets.Count; i++)
{
if (sheets[i].Name != dt.TableName) continue;
sheets[i].Name += "(副本)";
existSheetName = sheets[i].Name;
}
sheet = (Worksheet)sheets.Add(sheets[1], miss, miss, miss);
SetWorkSheetValue(excel, sheet, dt, fileName);
workbook.Save();
if (!string.IsNullOrEmpty(existSheetName))
sheets[existSheetName].Delete();
}
else
{
workbook = excel.Workbooks.Add(true);
sheet = (Worksheet)workbook.ActiveSheet;
SetWorkSheetValue(excel, sheet, dt, fileName);
// workbook.SaveAs(fileName, XlFileFormat.xlOpenDocumentSpreadsheet, miss, miss, miss, miss,
// XlSaveAsAccessMode.xlExclusive, miss, miss, miss, miss, miss);
workbook.SaveAs(fileName, miss, miss, miss, miss, miss,
XlSaveAsAccessMode.xlNoChange, miss, miss, miss, miss, miss);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
workbook.Close(true, Missing.Value, Missing.Value);
excel.Quit();
Kill(excel); //调用kill当前excel进程
ReleaseObject(workbook);
ReleaseObject(sheet);
ReleaseObject(excel);
}
}
// private void WriteExcelByDataSet(DataSet dsExcel, string fileName)
// {
// //_writeSheetName = new List<string>();
// foreach (DataTable dtExcel in dsExcel.Tables)
// {
// if (dtExcel == null || dtExcel.TableName == null || dtExcel.TableName == "") continue;
// ListHelper.RemoveEmptyRow(dtExcel);
// //_dtExcel = dt;
// WriteExcelByDataTable(dtExcel, fileName);
// }
// }
private static void WriteExcel_Completed(object sender, BackgroundWorkerEventArgs e)
{
Process.Start(SaveFileDialog.FileName);
// MessageBox.Show("导出完成");
// MessageBox.Show(e.BackGroundException == null
// ? Path.GetFileName(_filePath) + "文件写入成功!"
// : Path.GetFileName(_filePath) + "文件写入失败,请联系管理员!");
}
}
}