老师布置了一个任务,就是从txt文件中提取到一些信息
然后有一个Excel的模板
需要把数据导入进去,并且完成校验,最后保存Excel文件等一系列事件
我首先想到了国人开发的NPOI—因为它可以处理Excel和Word文件等等
在我处理的过程中,出现了一个问题,可能因为自己学艺不精,所以在此贴出自己写的代码为以后学会了纠错
方法一:NPOI——现在没有找到为什么ShiftRow会删除下两行的内容的问题
这些代码分别是打开workbook、插入N行数据
public HSSFWorkbook NPOIOpenExcel(string FileName){HSSFWorkbook MyHSSFWorkBook;FileStream fs = new FileStream(FileName, FileMode.Open);MyHSSFWorkBook = new HSSFWorkbook(fs);return MyHSSFWorkBook;}public XSSFWorkbook NPOIOpenExcel2(string FileName){XSSFWorkbook MyXSSFWorkBook;FileStream fs = new FileStream(FileName, FileMode.Open);MyXSSFWorkBook = new XSSFWorkbook(fs);return MyXSSFWorkBook;}//参数说明//第一个:指定操作的Sheet。//第二个:指定在第几行指入(插入行的位置)//第三个:指定要插入多少行//第四个:源单元格格式的行,private void MyInsertRow(ref HSSFSheet sheet, int startrow, int rowcount, HSSFRow FormatRow){//批量移动行sheet.ShiftRows(startrow,sheet.LastRowNum,rowcount,true,false,true);//对批量移动后空出的空行插,创建相应的行,并以插入行的上一行为格式源(即:插入行-1的那一行)for (int i = startrow; i < startrow + rowcount - 1; i++){HSSFRow targetRow = null;HSSFCell sourceCell = null;HSSFCell targetCell = null;targetRow = (HSSFRow)sheet.CreateRow(i + 1);for (int m = FormatRow.FirstCellNum; m < FormatRow.LastCellNum; m++){sourceCell = (HSSFCell)FormatRow.GetCell(m);if (sourceCell == null)continue;targetCell = (HSSFCell)targetRow.CreateCell(m);//targetCell.Encoding = sourceCell.Encoding;targetCell.CellStyle = sourceCell.CellStyle;targetCell.SetCellType(sourceCell.CellType);}//CopyRow(sourceRow, targetRow);//Util.CopyRow(sheet, sourceRow, targetRow);}HSSFRow firstTargetRow = (HSSFRow)sheet.GetRow(startrow);HSSFCell firstSourceCell = null;HSSFCell firstTargetCell = null;for (int m = FormatRow.FirstCellNum; m < FormatRow.LastCellNum; m++){firstSourceCell = (HSSFCell)FormatRow.GetCell(m);if (firstSourceCell == null)continue;firstTargetCell = (HSSFCell)firstTargetRow.CreateCell(m);//firstTargetCell.Encoding = firstSourceCell.Encoding;firstTargetCell.CellStyle = firstSourceCell.CellStyle;firstTargetCell.SetCellType(firstSourceCell.CellType);}}private void MyInsertRow(ref XSSFSheet sheet, int startrow, int rowcount, XSSFRow FormatRow){//批量移动行sheet.ShiftRows(startrow, sheet.LastRowNum, rowcount, true, false);//对批量移动后空出的空行插,创建相应的行,并以插入行的上一行为格式源(即:插入行-1的那一行)for (int i = startrow; i < startrow + rowcount - 1; i++){XSSFRow targetRow = null;XSSFCell sourceCell = null;XSSFCell targetCell = null;targetRow = (XSSFRow)sheet.CreateRow(i + 1);for (int m = FormatRow.FirstCellNum; m < FormatRow.LastCellNum; m++){sourceCell = (XSSFCell)FormatRow.GetCell(m);if (sourceCell == null)continue;targetCell = (XSSFCell)targetRow.CreateCell(m);//targetCell.Encoding = sourceCell.Encoding;targetCell.CellStyle = sourceCell.CellStyle;targetCell.SetCellType(sourceCell.CellType);}//CopyRow(sourceRow, targetRow);//Util.CopyRow(sheet, sourceRow, targetRow);}XSSFRow firstTargetRow = (XSSFRow)sheet.GetRow(startrow);XSSFCell firstSourceCell = null;XSSFCell firstTargetCell = null;for (int m = FormatRow.FirstCellNum; m < FormatRow.LastCellNum; m++){firstSourceCell = (XSSFCell)FormatRow.GetCell(m);if (firstSourceCell == null)continue;firstTargetCell = (XSSFCell)firstTargetRow.CreateCell(m);//firstTargetCell.Encoding = firstSourceCell.Encoding;firstTargetCell.CellStyle = firstSourceCell.CellStyle;firstTargetCell.SetCellType(firstSourceCell.CellType);}}private void SaveExcel(string dir,XSSFWorkbook workbook){using (FileStream files = new FileStream(dir, FileMode.Create)){workbook.Write(files);}}

但是插入N行之后,最后三行footer内容消失了
用的是这个方法
private void ButtonClick(object sender,ItemClickEventArgs e){DirectoryInfo d = GetDirectoryInfo(3);string modelPath = d.FullName + "CTCS_ExcelModel.xlsx";List<TxtPoint> points = new List<TxtPoint>();points.Add(new TxtPoint { Bear = 0.29038476533, DeltaBear = 0.089987576 });points.Add(new TxtPoint { Bear = 0.23984676, DeltaBear = 0.1231243566 });points.Add(new TxtPoint { Bear = 0.012398675, DeltaBear = 11.2345645756 });points.Add(new TxtPoint { Bear = 0.29038476533, DeltaBear = 0.089987576 });points.Add(new TxtPoint { Bear = 0.23984676, DeltaBear = 0.1231243566 });points.Add(new TxtPoint { Bear = 0.012398675, DeltaBear = 11.2345645756 });points.Add(new TxtPoint { Bear = 0.012398675, DeltaBear = 11.2345645756 });points.Add(new TxtPoint { Bear = 0.29038476533, DeltaBear = 0.089987576 });points.Add(new TxtPoint { Bear = 0.23984676, DeltaBear = 0.1231243566 });points.Add(new TxtPoint { Bear = 0.012398675, DeltaBear = 11.2345645756 });XSSFWorkbook workbook = NPOIOpenExcel2(modelPath);XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0);XSSFRow formatRow = (XSSFRow)sheet.GetRow(3);MyInsertRow(ref sheet, 6, points.Count - 4, formatRow);////ImportData(ref sheet, 2, points);//导入数据SaveExcel(d.FullName + "副本CTCS_ExcelModel.xlsx", workbook);}
否则用这个方法,则会出现这个问题
/// <summary>/// NPOI使用ShiftRows向Excel插入行,并复制原有样式/// </summary>/// <param name="file"></param>模板文件/// <param name="dir">导出路径</param>public void ShiftRows(string file,string dir,List<TxtPoint> txtPoints){try{FileStream fs = new FileStream(file, FileMode.Open);XSSFWorkbook workbook = new XSSFWorkbook(fs);ISheet sheet = (XSSFSheet)workbook.GetSheetAt(0);int startRow = 3;// 6;//开始插入行索引//列控数据表0-地理信息表默认可填充四行数据//当导入的DataTable超出4行时,使用ShiftRows插入行if (txtPoints.Count > 4){//插入行Console.WriteLine(sheet.LastRowNum.ToString());sheet.ShiftRows(startRow, sheet.LastRowNum, txtPoints.Count - 4, false, false);// txtPoints.Count - 4, true, false);//sheet.ShiftRows(startRow, sheet.LastRowNum, txtPoints.Count - 4, true, false);var rowSource = sheet.GetRow(2);var rowStyle = rowSource.RowStyle;//获取当前行样式for (int i = startRow; i < startRow + txtPoints.Count-1; i++){var rowInsert = sheet.CreateRow(i);if (rowStyle != null){rowInsert.RowStyle = rowStyle;rowInsert.Height = rowSource.Height;}for (int col = 0; col < rowSource.LastCellNum; col++){var cellsource = rowSource.GetCell(col);var cellInsert = rowInsert.CreateCell(col);var cellStyle = cellsource.CellStyle;//设置单元格样式if (cellStyle != null){cellInsert.CellStyle = cellsource.CellStyle;}}}}//绑定数据for (int j = 0; j < txtPoints.Count; j++){TxtPoint t = txtPoints[j];IRow r = sheet.GetRow(j + 2);r.Cells[0].SetCellValue(j + 1);r.Cells[1].SetCellValue("江仓站");r.Cells[9].SetCellValue(t.Bear);r.Cells[10].SetCellValue(t.DeltaBear);}//sheet.GetRow//后续操作using (FileStream files = new FileStream(dir, FileMode.Create)){workbook.Write(files);}fs.Dispose();}catch(Exception ex){XtraMessageBox.Show(ex.Message);}}
不仅出现下三行内容消失,新增的行高度和格式也不同
这真是个无解的问题
在我一筹莫展的过了一天,然后想到DevExpress有一个可视的报表软件SpreadSheetControl
方法二:解决了我之前的更改模板的问题,而且可以在不影响Header和Footer的情况下,在中间插入格式的N行,并且暂时没发现问题!Nice!
我是直接用的DevExpress的Template Gallery中的SpreadSheet
步骤如下
基本操作,选择项目
找到SpreadSheet就可以很方便啦
首先贴出一些常用的打开。保存。插入N行的代码
//打开文件操作public static string OpenExcel(){OpenFileDialog fileDialog = new OpenFileDialog();fileDialog.Multiselect = true;fileDialog.Title = "请选择文件";fileDialog.Filter = "所有文件(*.xls)|*.xls"; //设置要选择的文件的类型if (fileDialog.ShowDialog() == DialogResult.OK){return fileDialog.FileName;//返回文件的完整路径}else{return null;}}//导入Excelprivate void ImportData(string filePath)//导入按钮{if (!string.IsNullOrEmpty(filePath)){IWorkbook workbook = spreadsheetControl.Document;workbook.LoadDocument(filePath);}}//保存Excel文件private void SaveExcel(){try{string s = GetDirectoryInfo(3).FullName + "副本CTCS_ExcelModel.xlsx";spreadsheetControl.SaveDocument(s,DocumentFormat.Xlsx);}catch (Exception ExError){XtraMessageBox.Show("该文件正被别的地方占用");ExError.ToString();}}public static DirectoryInfo GetDirectoryInfo(int index){string directoryindex = "";for (int i = 0; i < index; i++){directoryindex += @"..\";}DirectoryInfo di = new DirectoryInfo(string.Format("{0}{1}", System.Windows.Forms.Application.StartupPath, directoryindex));return di;}
不过本来写了这些打开、导入方法,好像这个demo已经包含了这些功能
所以这些我就注释掉了
private void spreadsheetCommandBarButtonItem190_ItemClick(object sender, ItemClickEventArgs e){//DirectoryInfo di = GetDirectoryInfo(3);//string file = di.FullName + "CTCS_ExcelModel.xlsx";//ImportExcel(file);}
一些插入行和获取行列信息的代码
//访问行Workbook workbook=new Workbook();//Access a Collection of rowsRowCollection rows = workbook.Worksheets[0].Rows;//Access the first row by its index in the collection of rows;Row firstRow_byIndex = rows[0];//Access ths first row by its unique nameRow firstRow_byName = rows["1"];访问列Workbook workbook=new Workbook();//Access a collection of columnsColumnCollection columns = workbook.Worksheets[0].Columns.//ColumnCollection columns=workbook.Worksheets[0].Columns;Column firstColumn_byIndex = columns[0];//Access the first column by its unique name;Column firstColumn_byName = columns["A"];//
一些更具体的使用方法来自如下:
https://blog.csdn.net/hotmee/article/details/50554381
接下来插入N行的思路是:先在指定位置添加Rows,这些Row是空白的无格式的,之后就需要CopyFrom,从现有行复制模板
这里要注意Insert(int index,int count);这里的index指的是,
/// <summary>/// 插入N行/// </summary>/// <param name="workbook">Excel工作区</param>/// <param name="sheetIndex">sheet索引</param>/// <param name="startRowIndex">开始插入行的索引(向下插入表的)</param>/// <param name="rowcount">插入的行数</param>private void InsertRows(IWorkbook workbook,int sheetIndex,int startRowIndex,int rowcount){Worksheet sheet = workbook.Worksheets[sheetIndex];RowCollection rows = sheet.Rows;//example://sheet.Rows.Insert(6, 5);//在行索引为6的行下方插入5行,即增加7、8、9、10、11sheet.Rows.Insert(startRowIndex, rowcount);for(int j=startRowIndex; j<startRowIndex+rowcount;j++){sheet.Rows[j].CopyFrom(sheet.Rows[3]);//复制行格式}}//使用方法//我在第6行下方添加了5行,并更改了格式//InsertRows(spreadsheetControl.Document, 0,6,5);
图示:
插入5行
稍微更改了一下
加上了formatRow的index
/// <summary>/// 插入N行/// </summary>/// <param name="workbook">Excel工作区</param>/// <param name="sheetIndex">sheet索引</param>/// <param name="startRowIndex">开始插入行的索引(向下插入表的)</param>/// <param name="rowcount">插入的行数</param>/// <param name="formatRowIndex">格式行的索引值</param>private void InsertRows(IWorkbook workbook,int sheetIndex,int startRowIndex,int rowcount,int formatRowIndex){Worksheet sheet = workbook.Worksheets[sheetIndex];RowCollection rows = sheet.Rows;//example://sheet.Rows.Insert(6, 5);//在行索引为6的行下方插入5行,即增加7、8、9、10、11sheet.Rows.Insert(startRowIndex, rowcount);for(int j=startRowIndex; j<startRowIndex+rowcount;j++){sheet.Rows[j].CopyFrom(sheet.Rows[formatRowIndex-1]);//复制行格式}}
就成了复制第三行的样式
SpreadSheet合并和取消合并方法
//取消合并
sheet.UnMergeCells(sheet.Range[“D2:J2”]);、
//合并
sheet.MergeCells(sheet.Range[“D2:D3”]);
行删除
//更改cell的边框格式为OutLine
sheet.Cells[“D2”].Borders.SetOutsideBorders(Color.Black, BorderLineStyle.Medium);
