SVN r1211
SVN-Revision: r1211
This commit is contained in:
@@ -52,6 +52,7 @@ using DevExpress.Utils;
|
||||
using System.Data.Common;
|
||||
using DevExpress.Spreadsheet;
|
||||
using DevExpress.Docs;
|
||||
using OfficeOpenXml;
|
||||
|
||||
namespace Lskj.Control.Model
|
||||
{
|
||||
@@ -1187,7 +1188,13 @@ namespace Lskj.Control.Model
|
||||
dialog.FileName = menuName + DateTime.Now.ToString(SystemInfo.Instance.ExportFileDateFormat) + suffix;
|
||||
dialog.Filter = SystemInfo.Instance.IsXlsxFirst ? "Excel文件(*.xlsx)|*.xlsx|Excel文件(*.xls)|*.xls|PDF文件|*.PDF|RTF文件|*.RTF|HTML文件|*.html" :
|
||||
"Excel文件(*.xls)|*.xls|Excel文件(*.xlsx)|*.xlsx|PDF文件|*.PDF|RTF文件|*.RTF|HTML文件|*.html";
|
||||
if (SystemInfo.Instance.IsInsertWorksheet) dialog.OverwritePrompt = false; // 不弹系统“是否替换”
|
||||
string FileName = string.Empty;
|
||||
DialogResult result = dialog.ShowDialog();
|
||||
if (!PrepareInsertWorksheetExport(dialog, menuName, result, ref FileName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
WaitForm.ShowForm("导出中,请稍后...");
|
||||
@@ -1254,6 +1261,10 @@ namespace Lskj.Control.Model
|
||||
if (bandedGridControlEx.gridControl.Tag is PanelControl) panel = bandedGridControlEx.gridControl.Tag as PanelControl;
|
||||
SetModuleName(dialog.FileName, fileExt, gridView.Columns.Cast<GridColumn>().Count(column => column.Visible), true, panel);
|
||||
}
|
||||
if (SystemInfo.Instance.IsInsertWorksheet && !string.IsNullOrWhiteSpace(FileName))
|
||||
{
|
||||
AppendWorksheetToExcel(dialog.FileName, FileName);
|
||||
}
|
||||
MessageUtil.Show(ResourceKeys.ExportSuccess);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1297,11 +1308,21 @@ namespace Lskj.Control.Model
|
||||
dialog.Filter = SystemInfo.Instance.IsXlsxFirst ? "Excel文件(*.xlsx)|*.xlsx|Excel文件(*.xls)|*.xls|PDF文件|*.PDF|RTF文件|*.RTF|HTML文件|*.html" :
|
||||
"Excel文件(*.xls)|*.xls|Excel文件(*.xlsx)|*.xlsx|PDF文件|*.PDF|RTF文件|*.RTF|HTML文件|*.html";
|
||||
|
||||
|
||||
if (SystemInfo.Instance.IsInsertWorksheet) dialog.OverwritePrompt = false; // 不弹系统“是否替换”
|
||||
string FileName = string.Empty;
|
||||
|
||||
DialogResult result = dialog.ShowDialog();
|
||||
|
||||
if (!PrepareInsertWorksheetExport(dialog, menuName, result, ref FileName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
WaitForm.ShowForm("导出中,请稍后...");
|
||||
|
||||
try
|
||||
{
|
||||
//获取设置的导出列
|
||||
@@ -1490,6 +1511,12 @@ namespace Lskj.Control.Model
|
||||
SetModuleName(dialog.FileName, fileExt, gridView.Columns.Cast<GridColumn>().Count(column => column.Visible), false, panel);
|
||||
}
|
||||
|
||||
if (SystemInfo.Instance.IsInsertWorksheet &&!string.IsNullOrWhiteSpace(FileName))
|
||||
{
|
||||
AppendWorksheetToExcel(dialog.FileName, FileName);
|
||||
}
|
||||
|
||||
|
||||
MessageUtil.Show(ResourceKeys.ExportSuccess);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1765,8 +1792,14 @@ namespace Lskj.Control.Model
|
||||
dialog.Title = "导出";
|
||||
dialog.FileName = menuName + DateTime.Now.ToString(SystemInfo.Instance.ExportFileDateFormat) + ".xls";
|
||||
dialog.Filter = "Excel文件(*.xls)|*.xls|Excel2007|*.xlsx|PDF文件|*.PDF|RTF文件|*.RTF|HTML文件|*.html";
|
||||
if (SystemInfo.Instance.IsInsertWorksheet) dialog.OverwritePrompt = false; // 不弹系统“是否替换”
|
||||
string FileName = string.Empty;
|
||||
|
||||
DialogResult result = dialog.ShowDialog();
|
||||
if (!PrepareInsertWorksheetExport(dialog, menuName, result, ref FileName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
WaitForm.ShowForm("导出中,请稍后...");
|
||||
@@ -1796,6 +1829,10 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
control.ExportToHtml(dialog.FileName);
|
||||
}
|
||||
if (SystemInfo.Instance.IsInsertWorksheet && !string.IsNullOrWhiteSpace(FileName))
|
||||
{
|
||||
AppendWorksheetToExcel(dialog.FileName, FileName);
|
||||
}
|
||||
|
||||
MessageUtil.Show(ResourceKeys.ExportSuccess);
|
||||
}
|
||||
@@ -2092,8 +2129,6 @@ namespace Lskj.Control.Model
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>说明:获取GridView过滤或排序后的数据集</para>
|
||||
/// <para>创建人:龚宇超</para>
|
||||
@@ -2274,7 +2309,7 @@ namespace Lskj.Control.Model
|
||||
/// </summary>
|
||||
/// <param name="colFields">The col fields.</param>
|
||||
/// <param name="AutoImportCalMode">导入时是否触发关联计算(模块配置)</param>
|
||||
public static DataTable ToExcelDataTable(this GridView gridView, string fileName, string colFields, bool isDirectImport = false, bool isBillImport = false,bool AutoImportCalMode = false)
|
||||
public static DataTable ToExcelDataTable(this GridView gridView, string fileName, string colFields, bool isDirectImport = false, bool isBillImport = false, bool AutoImportCalMode = false)
|
||||
{
|
||||
DataTable table = new DataTable();
|
||||
int index = gridView is BandedGridView ? 1 : 0;
|
||||
@@ -2361,7 +2396,7 @@ namespace Lskj.Control.Model
|
||||
table.Columns.Add("lskjimport_errorFlag");
|
||||
|
||||
|
||||
bool AutoImportCal = SystemInfo.Instance.AutoImportCal|| AutoImportCalMode;//是否执行 关联和计算公式
|
||||
bool AutoImportCal = SystemInfo.Instance.AutoImportCal || AutoImportCalMode;//是否执行 关联和计算公式
|
||||
//bool ImportDefaultValue= SystemInfo.Instance.ImportDefaultValue;//是否为空单元格添加默认值
|
||||
//bool isImportRows = true;//是否是导入行(如果是合计行就不触发默认值)
|
||||
// 添加行
|
||||
@@ -2392,7 +2427,7 @@ namespace Lskj.Control.Model
|
||||
col = index != 1 ? gridView.Columns.OfType<GridColumn>().FirstOrDefault(x => Regex.Replace(x.Caption, @"\s", "") == Regex.Replace(headcell.ToString(), @"\s", "")) : newBandGrid.Columns.OfType<BandedGridColumn>().FirstOrDefault(x => Regex.Replace(x.OwnerBand + x.Caption, @"\s", "") == Regex.Replace(bandTitel + headcell.ToString(), @"\s", ""));
|
||||
if (col == null) continue;
|
||||
GridColumnModel model = col.Tag as GridColumnModel;
|
||||
|
||||
|
||||
if (cell != null)
|
||||
{
|
||||
if (cell.CellType == CellType.Error)
|
||||
@@ -2504,7 +2539,7 @@ namespace Lskj.Control.Model
|
||||
|| model.FieldType == ControlType.LabAutoGridValue
|
||||
|| model.FieldType == ControlType.LabAutoGridValueParam
|
||||
|| model.FieldType == ControlType.LabSelectReturnId
|
||||
|| (model.FieldType == ControlType.LabSelectReturnIdNew && model.ModuleFrameDisplayText)||
|
||||
|| (model.FieldType == ControlType.LabSelectReturnIdNew && model.ModuleFrameDisplayText) ||
|
||||
model.FieldType == ControlType.LabModuleAddRowsID
|
||||
))
|
||||
{
|
||||
@@ -2734,7 +2769,7 @@ namespace Lskj.Control.Model
|
||||
if (colFields.IndexOf("lskjimport_errorFlag") != -1 && !table.Columns.Contains("lskjimport_errorFlag"))
|
||||
table.Columns.Add("lskjimport_errorFlag");
|
||||
|
||||
bool AutoImportCal = SystemInfo.Instance.AutoImportCal|| AutoImportCalMode;//是否执行 计算公式
|
||||
bool AutoImportCal = SystemInfo.Instance.AutoImportCal || AutoImportCalMode;//是否执行 计算公式
|
||||
//bool ImportDefaultValue= SystemInfo.Instance.ImportDefaultValue;//是否为空单元格添加默认值
|
||||
//bool isImportRows = true;//是否是导入行(如果是合计行就不触发默认值)
|
||||
// 添加行
|
||||
@@ -2852,7 +2887,7 @@ namespace Lskj.Control.Model
|
||||
|| model.FieldType == ControlType.LabAutoGridValue
|
||||
|| model.FieldType == ControlType.LabAutoGridValueParam
|
||||
|| model.FieldType == ControlType.LabSelectReturnId
|
||||
|| (model.FieldType == ControlType.LabSelectReturnIdNew && model.ModuleFrameDisplayText)||
|
||||
|| (model.FieldType == ControlType.LabSelectReturnIdNew && model.ModuleFrameDisplayText) ||
|
||||
model.FieldType == ControlType.LabModuleAddRowsID
|
||||
))
|
||||
{
|
||||
@@ -3086,7 +3121,7 @@ namespace Lskj.Control.Model
|
||||
|
||||
string fileName = dialog.FileName;
|
||||
string colFields = gridControlEx.GridView.Columns.ToString(',');
|
||||
ImportTable = gridControlEx.GridView.ToExcelDataTable(fileName, colFields, true,false, SysModel.AutoImportCalMode);
|
||||
ImportTable = gridControlEx.GridView.ToExcelDataTable(fileName, colFields, true, false, SysModel.AutoImportCalMode);
|
||||
|
||||
|
||||
if (ImportTable == null && ImportTable.Rows.Count < 1)
|
||||
@@ -3192,7 +3227,7 @@ namespace Lskj.Control.Model
|
||||
DbDataAdapter dat = BaseImpl.GetAdapterResult(sql);
|
||||
DbCommandBuilder cb = SqlHelper.dbFactory.CreateCommandBuilder();
|
||||
cb.DataAdapter = dat;
|
||||
// SqlCommandBuilder scb = new SqlCommandBuilder(dat);
|
||||
// SqlCommandBuilder scb = new SqlCommandBuilder(dat);
|
||||
DataTable datatb = new DataTable();
|
||||
DataTable failedData = new DataTable();
|
||||
dat.Fill(datatb);
|
||||
@@ -3282,7 +3317,7 @@ namespace Lskj.Control.Model
|
||||
model.FieldType == ControlType.LabMultiSelectValueParam ||
|
||||
model.FieldType == ControlType.LabAutoGridValue ||
|
||||
model.FieldType == ControlType.LabSelectReturnId ||
|
||||
(model.FieldType == ControlType.LabSelectReturnIdNew && model.ModuleFrameDisplayText)||
|
||||
(model.FieldType == ControlType.LabSelectReturnIdNew && model.ModuleFrameDisplayText) ||
|
||||
model.FieldType == ControlType.LabModuleAddRowsID
|
||||
))
|
||||
{
|
||||
@@ -3699,7 +3734,7 @@ namespace Lskj.Control.Model
|
||||
|| model.FieldType == ControlType.LabAutoGridValue
|
||||
|| model.FieldType == ControlType.LabAutoGridValueParam
|
||||
|| model.FieldType == ControlType.LabSelectReturnId
|
||||
|| (model.FieldType == ControlType.LabSelectReturnIdNew && model.ModuleFrameDisplayText)||
|
||||
|| (model.FieldType == ControlType.LabSelectReturnIdNew && model.ModuleFrameDisplayText) ||
|
||||
model.FieldType == ControlType.LabModuleAddRowsID
|
||||
)
|
||||
{
|
||||
@@ -3781,9 +3816,9 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
string sqlValue = model.SqlSource;
|
||||
|
||||
if (model.FieldType == ControlType.LabSelectReturnId || model.FieldType == ControlType.LabSelectReturnIdNew|| model.FieldType == ControlType.LabModuleAddRowsID)
|
||||
if (model.FieldType == ControlType.LabSelectReturnId || model.FieldType == ControlType.LabSelectReturnIdNew || model.FieldType == ControlType.LabModuleAddRowsID)
|
||||
{
|
||||
if ((model.IsRadio && !string.IsNullOrWhiteSpace(model.addModuleld)) || model.FieldType == ControlType.LabSelectReturnIdNew|| model.FieldType == ControlType.LabModuleAddRowsID)
|
||||
if ((model.IsRadio && !string.IsNullOrWhiteSpace(model.addModuleld)) || model.FieldType == ControlType.LabSelectReturnIdNew || model.FieldType == ControlType.LabModuleAddRowsID)
|
||||
{
|
||||
//单选模式数据源为模块sql 新版模块选中返回id固定位模块sql
|
||||
DataRow modelRow = Business.Impl.MainImpl.GetSystemdllTab(model.addModuleld);
|
||||
@@ -4089,4 +4124,495 @@ namespace Lskj.Control.Model
|
||||
// 设置填充模式为实心填充
|
||||
cellStyle.FillPattern = FillPattern.SolidForeground;
|
||||
}
|
||||
|
||||
cell.CellStyle = cellStyle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 保存更改回原始文件
|
||||
using (FileStream file = new FileStream(excelFilePath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
workbook.Write(file);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在未保存的数据
|
||||
/// </summary>
|
||||
/// <param name="control"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDataNotSaved(this GridControlEx control)
|
||||
{
|
||||
DataTable table = control.gridControl.DataSource as DataTable;
|
||||
foreach (DataRow row in table.Rows)
|
||||
{
|
||||
if (row.RowState == DataRowState.Modified || row.RowState == DataRowState.Added)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 准备追加工作表导出:用户选择已存在Excel文件时,先切换到临时文件导出,导出完成后再追加到原文件。
|
||||
/// </summary>
|
||||
/// <param name="dialog">保存文件对话框。</param>
|
||||
/// <param name="menuName">默认工作表名称。</param>
|
||||
/// <param name="result">保存文件对话框返回结果。</param>
|
||||
/// <param name="targetFileName">用户选择的原Excel文件路径。</param>
|
||||
/// <returns>是否继续导出。</returns>
|
||||
private static bool PrepareInsertWorksheetExport(SaveFileDialog dialog, string menuName, DialogResult result, ref string targetFileName)
|
||||
{
|
||||
if (result != DialogResult.OK || !SystemInfo.Instance.IsInsertWorksheet || !File.Exists(dialog.FileName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
string selectedFileExt = Path.GetExtension(dialog.FileName).ToLower();
|
||||
if (!selectedFileExt.Equals(".xlsx") && !selectedFileExt.Equals(".xls"))
|
||||
{
|
||||
MessageUtil.Show("追加工作表功能只支持.xls/.xlsx文件,请选择Excel文件。");
|
||||
return false;
|
||||
}
|
||||
|
||||
FrmSettingTableName frmSettingTableName = new FrmSettingTableName(menuName + DateTime.Now.ToString(SystemInfo.Instance.ExportFileDateFormat));
|
||||
if (frmSettingTableName.ShowDialog() != DialogResult.OK)
|
||||
{
|
||||
// 不导出
|
||||
return false;
|
||||
}
|
||||
|
||||
// 添加页签的形式导出:先保存原文件路径,再将当前导出路径切换到临时文件。
|
||||
targetFileName = dialog.FileName;
|
||||
PubUtil.ClearFilesInDirectory(PubUtil.ExportFilePath);
|
||||
string tempFileName = GetSafeExcelFileName(frmSettingTableName.TabName) + selectedFileExt;
|
||||
dialog.FileName = Path.Combine(PubUtil.ExportFilePath, tempFileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将临时导出的Excel工作表追加到用户选择的Excel文件中。
|
||||
/// </summary>
|
||||
/// <param name="sourceFileName">临时导出的Excel文件路径。</param>
|
||||
/// <param name="targetFileName">用户选择的原Excel文件路径。</param>
|
||||
private static void AppendWorksheetToExcel(string sourceFileName, string targetFileName)
|
||||
{
|
||||
// 追加工作表只处理xlsx文件,避免xls/pdf/rtf/html走入不支持的合并逻辑。
|
||||
if (string.IsNullOrWhiteSpace(sourceFileName) || string.IsNullOrWhiteSpace(targetFileName))
|
||||
{
|
||||
throw new Exception("追加工作表失败:文件路径不能为空。");
|
||||
}
|
||||
if (!File.Exists(sourceFileName))
|
||||
{
|
||||
throw new Exception("追加工作表失败:未找到临时导出文件。");
|
||||
}
|
||||
if (!File.Exists(targetFileName))
|
||||
{
|
||||
throw new Exception("追加工作表失败:未找到需要追加的Excel文件。");
|
||||
}
|
||||
string fileExt = Path.GetExtension(targetFileName).ToLower();
|
||||
if (!Path.GetExtension(sourceFileName).ToLower().Equals(fileExt) || (!fileExt.Equals(".xlsx") && !fileExt.Equals(".xls")))
|
||||
{
|
||||
throw new Exception("追加工作表失败:追加工作表功能只支持.xls/.xlsx文件。");
|
||||
}
|
||||
|
||||
if (fileExt.Equals(".xls"))
|
||||
{
|
||||
AppendXlsWorksheetToExcel(sourceFileName, targetFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
// EPPlus 5及以上版本要求先设置LicenseContext,否则创建ExcelPackage时会报LicenseException。
|
||||
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
|
||||
|
||||
FileInfo targetFileInfo = new FileInfo(targetFileName);
|
||||
using (FileStream sourceStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (ExcelPackage sourcePackage = new ExcelPackage(sourceStream))
|
||||
using (ExcelPackage targetPackage = new ExcelPackage(targetFileInfo))
|
||||
{
|
||||
ExcelWorksheet sourceSheet = GetFirstVisibleWorksheet(sourcePackage);
|
||||
if (sourceSheet == null || sourceSheet.Dimension == null)
|
||||
{
|
||||
throw new Exception("追加工作表失败:临时导出文件中没有可追加的数据。");
|
||||
}
|
||||
|
||||
// 使用临时文件名作为用户输入的工作表名称,并处理重名和Excel名称限制。
|
||||
string sheetName = GetUniqueWorksheetName(targetPackage, Path.GetFileNameWithoutExtension(sourceFileName));
|
||||
try
|
||||
{
|
||||
// 优先复制整个工作表,最大程度保留字体、边框、筛选、列宽等导出格式。
|
||||
targetPackage.Workbook.Worksheets.Add(sheetName, sourceSheet);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 整表复制失败时,退回到逐格复制,仍然尽量保留单元格样式。
|
||||
if (targetPackage.Workbook.Worksheets[sheetName] != null)
|
||||
{
|
||||
targetPackage.Workbook.Worksheets.Delete(sheetName);
|
||||
}
|
||||
ExcelWorksheet targetSheet = targetPackage.Workbook.Worksheets.Add(sheetName);
|
||||
SafeCopyXlsxWorksheetContent(sourceSheet, targetSheet);
|
||||
}
|
||||
targetPackage.Save();
|
||||
}
|
||||
|
||||
// 合并成功后删除临时文件,删除失败不影响导出结果。
|
||||
try
|
||||
{
|
||||
File.Delete(sourceFileName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将临时导出的xls工作表追加到用户选择的xls文件中。
|
||||
/// </summary>
|
||||
/// <param name="sourceFileName">临时导出的xls文件路径。</param>
|
||||
/// <param name="targetFileName">用户选择的原xls文件路径。</param>
|
||||
private static void AppendXlsWorksheetToExcel(string sourceFileName, string targetFileName)
|
||||
{
|
||||
HSSFWorkbook sourceWorkbook;
|
||||
HSSFWorkbook targetWorkbook;
|
||||
|
||||
using (FileStream sourceStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
sourceWorkbook = new HSSFWorkbook(sourceStream);
|
||||
}
|
||||
|
||||
using (FileStream targetStream = new FileStream(targetFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
targetWorkbook = new HSSFWorkbook(targetStream);
|
||||
}
|
||||
|
||||
ISheet sourceSheet = GetFirstVisibleNpoiSheet(sourceWorkbook);
|
||||
if (sourceSheet == null || sourceSheet.PhysicalNumberOfRows == 0)
|
||||
{
|
||||
throw new Exception("追加工作表失败:临时导出文件中没有可追加的数据。");
|
||||
}
|
||||
|
||||
string sheetName = GetUniqueNpoiSheetName(targetWorkbook, Path.GetFileNameWithoutExtension(sourceFileName));
|
||||
ISheet targetSheet = targetWorkbook.CreateSheet(sheetName);
|
||||
SafeCopyNpoiWorksheetContent(sourceSheet, targetSheet, targetWorkbook);
|
||||
|
||||
using (FileStream targetStream = new FileStream(targetFileName, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
targetWorkbook.Write(targetStream);
|
||||
}
|
||||
|
||||
// 合并成功后删除临时文件,删除失败不影响导出结果。
|
||||
try
|
||||
{
|
||||
File.Delete(sourceFileName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取源Excel中第一个可见且有数据的工作表。
|
||||
/// </summary>
|
||||
/// <param name="package">Excel文件包。</param>
|
||||
/// <returns>可追加的工作表。</returns>
|
||||
private static ExcelWorksheet GetFirstVisibleWorksheet(ExcelPackage package)
|
||||
{
|
||||
foreach (ExcelWorksheet worksheet in package.Workbook.Worksheets)
|
||||
{
|
||||
if (worksheet != null && worksheet.Hidden == eWorkSheetHidden.Visible && worksheet.Dimension != null)
|
||||
{
|
||||
return worksheet;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取xls源文件中第一个可见且有数据的工作表。
|
||||
/// </summary>
|
||||
/// <param name="workbook">xls工作簿。</param>
|
||||
/// <returns>可追加的工作表。</returns>
|
||||
private static ISheet GetFirstVisibleNpoiSheet(HSSFWorkbook workbook)
|
||||
{
|
||||
for (int i = 0; i < workbook.NumberOfSheets; i++)
|
||||
{
|
||||
if (!workbook.IsSheetHidden(i) && !workbook.IsSheetVeryHidden(i))
|
||||
{
|
||||
ISheet sheet = workbook.GetSheetAt(i);
|
||||
if (sheet != null && sheet.PhysicalNumberOfRows > 0)
|
||||
{
|
||||
return sheet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全复制xlsx工作表内容,复制数据、样式、列宽、行高和合并区域。
|
||||
/// </summary>
|
||||
/// <param name="sourceSheet">源工作表。</param>
|
||||
/// <param name="targetSheet">目标工作表。</param>
|
||||
private static void SafeCopyXlsxWorksheetContent(ExcelWorksheet sourceSheet, ExcelWorksheet targetSheet)
|
||||
{
|
||||
int startRow = sourceSheet.Dimension.Start.Row;
|
||||
int startCol = sourceSheet.Dimension.Start.Column;
|
||||
int endRow = sourceSheet.Dimension.End.Row;
|
||||
int endCol = sourceSheet.Dimension.End.Column;
|
||||
|
||||
sourceSheet.Cells[startRow, startCol, endRow, endCol].Copy(targetSheet.Cells[startRow, startCol, endRow, endCol]);
|
||||
|
||||
for (int row = startRow; row <= endRow; row++)
|
||||
{
|
||||
targetSheet.Row(row).Height = sourceSheet.Row(row).Height;
|
||||
targetSheet.Row(row).Hidden = sourceSheet.Row(row).Hidden;
|
||||
}
|
||||
|
||||
for (int col = startCol; col <= endCol; col++)
|
||||
{
|
||||
targetSheet.Column(col).Width = sourceSheet.Column(col).Width;
|
||||
targetSheet.Column(col).Hidden = sourceSheet.Column(col).Hidden;
|
||||
}
|
||||
|
||||
foreach (string address in sourceSheet.MergedCells)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
targetSheet.Cells[address].Merge = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceSheet.View != null)
|
||||
{
|
||||
targetSheet.View.ShowGridLines = sourceSheet.View.ShowGridLines;
|
||||
targetSheet.View.ZoomScale = sourceSheet.View.ZoomScale;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全复制xls工作表内容,复制数据、字体样式、列宽、行高和合并区域。
|
||||
/// </summary>
|
||||
/// <param name="sourceSheet">源工作表。</param>
|
||||
/// <param name="targetSheet">目标工作表。</param>
|
||||
/// <param name="targetWorkbook">目标工作簿。</param>
|
||||
private static void SafeCopyNpoiWorksheetContent(ISheet sourceSheet, ISheet targetSheet, HSSFWorkbook targetWorkbook)
|
||||
{
|
||||
int firstColumnIndex = -1;
|
||||
int lastColumnIndex = -1;
|
||||
Dictionary<short, ICellStyle> styleCache = new Dictionary<short, ICellStyle>();
|
||||
|
||||
for (int rowIndex = sourceSheet.FirstRowNum; rowIndex <= sourceSheet.LastRowNum; rowIndex++)
|
||||
{
|
||||
IRow sourceRow = sourceSheet.GetRow(rowIndex);
|
||||
if (sourceRow == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sourceRow.FirstCellNum >= 0)
|
||||
{
|
||||
firstColumnIndex = firstColumnIndex < 0 ? sourceRow.FirstCellNum : Math.Min(firstColumnIndex, sourceRow.FirstCellNum);
|
||||
lastColumnIndex = Math.Max(lastColumnIndex, sourceRow.LastCellNum);
|
||||
}
|
||||
|
||||
IRow targetRow = targetSheet.CreateRow(rowIndex);
|
||||
targetRow.Height = sourceRow.Height;
|
||||
|
||||
for (int cellIndex = sourceRow.FirstCellNum; cellIndex < sourceRow.LastCellNum; cellIndex++)
|
||||
{
|
||||
if (cellIndex < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ICell sourceCell = sourceRow.GetCell(cellIndex);
|
||||
if (sourceCell == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ICell targetCell = targetRow.CreateCell(cellIndex);
|
||||
CopyNpoiCellValue(sourceCell, targetCell);
|
||||
CopyNpoiCellStyle(sourceCell, targetCell, targetWorkbook, styleCache);
|
||||
}
|
||||
}
|
||||
|
||||
if (firstColumnIndex >= 0 && lastColumnIndex > firstColumnIndex)
|
||||
{
|
||||
for (int colIndex = firstColumnIndex; colIndex < lastColumnIndex; colIndex++)
|
||||
{
|
||||
targetSheet.SetColumnWidth(colIndex, sourceSheet.GetColumnWidth(colIndex));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < sourceSheet.NumMergedRegions; i++)
|
||||
{
|
||||
CellRangeAddress sourceRange = sourceSheet.GetMergedRegion(i);
|
||||
if (sourceRange != null)
|
||||
{
|
||||
targetSheet.AddMergedRegion(new CellRangeAddress(
|
||||
sourceRange.FirstRow,
|
||||
sourceRange.LastRow,
|
||||
sourceRange.FirstColumn,
|
||||
sourceRange.LastColumn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制xls单元格的值。
|
||||
/// </summary>
|
||||
/// <param name="sourceCell">源单元格。</param>
|
||||
/// <param name="targetCell">目标单元格。</param>
|
||||
private static void CopyNpoiCellValue(ICell sourceCell, ICell targetCell)
|
||||
{
|
||||
switch (sourceCell.CellType)
|
||||
{
|
||||
case CellType.Boolean:
|
||||
targetCell.SetCellValue(sourceCell.BooleanCellValue);
|
||||
break;
|
||||
case CellType.Numeric:
|
||||
targetCell.SetCellValue(sourceCell.NumericCellValue);
|
||||
break;
|
||||
case CellType.String:
|
||||
targetCell.SetCellValue(sourceCell.StringCellValue);
|
||||
break;
|
||||
case CellType.Formula:
|
||||
targetCell.SetCellFormula(sourceCell.CellFormula);
|
||||
break;
|
||||
case CellType.Error:
|
||||
targetCell.SetCellErrorValue(sourceCell.ErrorCellValue);
|
||||
break;
|
||||
case CellType.Blank:
|
||||
targetCell.SetCellType(CellType.Blank);
|
||||
break;
|
||||
default:
|
||||
targetCell.SetCellValue(sourceCell.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制xls单元格样式和字体。
|
||||
/// </summary>
|
||||
/// <param name="sourceCell">源单元格。</param>
|
||||
/// <param name="targetCell">目标单元格。</param>
|
||||
/// <param name="targetWorkbook">目标工作簿。</param>
|
||||
/// <param name="styleCache">样式缓存,避免重复创建相同样式。</param>
|
||||
private static void CopyNpoiCellStyle(ICell sourceCell, ICell targetCell, HSSFWorkbook targetWorkbook, Dictionary<short, ICellStyle> styleCache)
|
||||
{
|
||||
if (sourceCell.CellStyle == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
short styleIndex = sourceCell.CellStyle.Index;
|
||||
ICellStyle targetStyle = null;
|
||||
if (!styleCache.TryGetValue(styleIndex, out targetStyle))
|
||||
{
|
||||
targetStyle = targetWorkbook.CreateCellStyle();
|
||||
targetStyle.CloneStyleFrom(sourceCell.CellStyle);
|
||||
|
||||
IFont sourceFont = sourceCell.CellStyle.GetFont(sourceCell.Sheet.Workbook);
|
||||
if (sourceFont != null)
|
||||
{
|
||||
IFont targetFont = targetWorkbook.CreateFont();
|
||||
CopyNpoiFont(sourceFont, targetFont);
|
||||
targetStyle.SetFont(targetFont);
|
||||
}
|
||||
|
||||
styleCache.Add(styleIndex, targetStyle);
|
||||
}
|
||||
|
||||
targetCell.CellStyle = targetStyle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制xls字体属性。
|
||||
/// </summary>
|
||||
/// <param name="sourceFont">源字体。</param>
|
||||
/// <param name="targetFont">目标字体。</param>
|
||||
private static void CopyNpoiFont(IFont sourceFont, IFont targetFont)
|
||||
{
|
||||
targetFont.FontName = sourceFont.FontName;
|
||||
targetFont.FontHeight = sourceFont.FontHeight;
|
||||
targetFont.FontHeightInPoints = sourceFont.FontHeightInPoints;
|
||||
targetFont.Boldweight = sourceFont.Boldweight;
|
||||
targetFont.Color = sourceFont.Color;
|
||||
targetFont.IsItalic = sourceFont.IsItalic;
|
||||
targetFont.IsStrikeout = sourceFont.IsStrikeout;
|
||||
targetFont.Underline = sourceFont.Underline;
|
||||
targetFont.TypeOffset = sourceFont.TypeOffset;
|
||||
targetFont.Charset = sourceFont.Charset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取不重复且符合Excel规则的工作表名称。
|
||||
/// </summary>
|
||||
/// <param name="package">目标Excel文件包。</param>
|
||||
/// <param name="sheetName">原始工作表名称。</param>
|
||||
/// <returns>可用的工作表名称。</returns>
|
||||
private static string GetUniqueWorksheetName(ExcelPackage package, string sheetName)
|
||||
{
|
||||
string baseName = GetSafeWorksheetName(sheetName);
|
||||
string result = baseName;
|
||||
int index = 1;
|
||||
while (package.Workbook.Worksheets.Any(item => string.Equals(item.Name, result, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
string suffix = "_" + index++;
|
||||
int maxLength = 31 - suffix.Length;
|
||||
string namePrefix = baseName.Length > maxLength ? baseName.Substring(0, maxLength) : baseName;
|
||||
result = namePrefix + suffix;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取xls中不重复且符合Excel规则的工作表名称。
|
||||
/// </summary>
|
||||
/// <param name="workbook">目标xls工作簿。</param>
|
||||
/// <param name="sheetName">原始工作表名称。</param>
|
||||
/// <returns>可用的工作表名称。</returns>
|
||||
private static string GetUniqueNpoiSheetName(HSSFWorkbook workbook, string sheetName)
|
||||
{
|
||||
string baseName = GetSafeWorksheetName(sheetName);
|
||||
string result = baseName;
|
||||
int index = 1;
|
||||
while (workbook.GetSheet(result) != null)
|
||||
{
|
||||
string suffix = "_" + index++;
|
||||
int maxLength = 31 - suffix.Length;
|
||||
string namePrefix = baseName.Length > maxLength ? baseName.Substring(0, maxLength) : baseName;
|
||||
result = namePrefix + suffix;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取符合Excel工作表命名规则的名称。
|
||||
/// </summary>
|
||||
/// <param name="sheetName">原始工作表名称。</param>
|
||||
/// <returns>处理后的工作表名称。</returns>
|
||||
private static string GetSafeWorksheetName(string sheetName)
|
||||
{
|
||||
string result = (sheetName ?? string.Empty).Trim();
|
||||
char[] invalidChars = new char[] { '\\', '/', '?', '*', '[', ']', ':' };
|
||||
foreach (char invalidChar in invalidChars)
|
||||
{
|
||||
result = result.Replace(invalidChar, '_');
|
||||
}
|
||||
result = Regex.Replace(result,
|
||||
Reference in New Issue
Block a user