Saya menemukan NPOI sangat bagus untuk menulis file Excel dengan C #.
Tetapi saya ingin membuka, membaca, dan memodifikasi file Excel di C #.
Bagaimana saya bisa melakukan ini?
Contoh bacaan sederhana di bawah ini:
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
//.....
private void button1_Click(object sender, EventArgs e)
{
HSSFWorkbook hssfwb;
using (FileStream file = new FileStream(@"c:\test.xls", FileMode.Open, FileAccess.Read))
{
hssfwb= new HSSFWorkbook(file);
}
ISheet sheet = hssfwb.GetSheet("Arkusz1");
for (int row = 0; row <= sheet.LastRowNum; row++)
{
if (sheet.GetRow(row) != null) //null is when the row only contains empty cells
{
MessageBox.Show(string.Format("Row {0} = {1}", row, sheet.GetRow(row).GetCell(0).StringCellValue));
}
}
}
Ngomong-ngomong: di situs web NPOI di sini di bagian Unduh ada paket contoh - paket contoh C #. Cobalah, jika Anda belum melakukannya. :)
Mungkin berguna untuk mengandalkan pabrik Buku Kerja untuk membuat instance objek buku kerja karena metode pabrik akan melakukan deteksi xls atau xlsx untuk Anda. Referensi: http://apache-poi.1045710.n5.nabble.com/How-to-check-for-valid-excel-files-using-POI-without-checking-the-file-extension-td2341055.html
Jika Anda tidak yakin dengan nama Sheet tetapi Anda yakin dengan indeksnya (berbasis 0), Anda dapat mengambil sheet seperti ini:
Anda kemudian dapat mengulang melalui baris menggunakan kode yang diberikan oleh jawaban yang diterima dari mj82
sumber
FileStream
,inputStream
should beFileMode.Open
danFileAccess.Read
, dan untuk menyimpan perubahan ke disk, Anda perlu membuka yang baruFileStream
denganFileAccess.Write
izin; sepertinya tidak berfungsi denganReadWrite
aliran. Selain ituWrite()
, NPOIIWorkbook
tampaknya tidak memilikiSave()
metode tipe yang memungkinkan merevisi buku kerja dan menyimpannya setelahnya, seperti yang dilakukan Excel Interop.Saya menemukan NPOI sangat berguna untuk bekerja dengan File Excel, berikut adalah implementasinya (Komentar dalam bahasa Spanyol, maaf untuk itu):
Metode ini Membuka file Excel (xls atau xlsx) dan mengubahnya menjadi DataTable.
/// <summary>Abre un archivo de Excel (xls o xlsx) y lo convierte en un DataTable. /// LA PRIMERA FILA DEBE CONTENER LOS NOMBRES DE LOS CAMPOS.</summary> /// <param name="pRutaArchivo">Ruta completa del archivo a abrir.</param> /// <param name="pHojaIndex">Número (basado en cero) de la hoja que se desea abrir. 0 es la primera hoja.</param> private DataTable Excel_To_DataTable(string pRutaArchivo, int pHojaIndex) { // --------------------------------- // /* REFERENCIAS: * NPOI.dll * NPOI.OOXML.dll * NPOI.OpenXml4Net.dll */ // --------------------------------- // /* USING: * using NPOI.SS.UserModel; * using NPOI.HSSF.UserModel; * using NPOI.XSSF.UserModel; */ // AUTOR: Ing. Jhollman Chacon R. 2015 // --------------------------------- // DataTable Tabla = null; try { if (System.IO.File.Exists(pRutaArchivo)) { IWorkbook workbook = null; //IWorkbook determina si es xls o xlsx ISheet worksheet = null; string first_sheet_name = ""; using (FileStream FS = new FileStream(pRutaArchivo, FileMode.Open, FileAccess.Read)) { workbook = WorkbookFactory.Create(FS); //Abre tanto XLS como XLSX worksheet = workbook.GetSheetAt(pHojaIndex); //Obtener Hoja por indice first_sheet_name = worksheet.SheetName; //Obtener el nombre de la Hoja Tabla = new DataTable(first_sheet_name); Tabla.Rows.Clear(); Tabla.Columns.Clear(); // Leer Fila por fila desde la primera for (int rowIndex = 0; rowIndex <= worksheet.LastRowNum; rowIndex++) { DataRow NewReg = null; IRow row = worksheet.GetRow(rowIndex); IRow row2 = null; IRow row3 = null; if (rowIndex == 0) { row2 = worksheet.GetRow(rowIndex + 1); //Si es la Primera fila, obtengo tambien la segunda para saber el tipo de datos row3 = worksheet.GetRow(rowIndex + 2); //Y la tercera tambien por las dudas } if (row != null) //null is when the row only contains empty cells { if (rowIndex > 0) NewReg = Tabla.NewRow(); int colIndex = 0; //Leer cada Columna de la fila foreach (ICell cell in row.Cells) { object valorCell = null; string cellType = ""; string[] cellType2 = new string[2]; if (rowIndex == 0) //Asumo que la primera fila contiene los titlos: { for (int i = 0; i < 2; i++) { ICell cell2 = null; if (i == 0) { cell2 = row2.GetCell(cell.ColumnIndex); } else { cell2 = row3.GetCell(cell.ColumnIndex); } if (cell2 != null) { switch (cell2.CellType) { case CellType.Blank: break; case CellType.Boolean: cellType2[i] = "System.Boolean"; break; case CellType.String: cellType2[i] = "System.String"; break; case CellType.Numeric: if (HSSFDateUtil.IsCellDateFormatted(cell2)) { cellType2[i] = "System.DateTime"; } else { cellType2[i] = "System.Double"; //valorCell = cell2.NumericCellValue; } break; case CellType.Formula: bool continuar = true; switch (cell2.CachedFormulaResultType) { case CellType.Boolean: cellType2[i] = "System.Boolean"; break; case CellType.String: cellType2[i] = "System.String"; break; case CellType.Numeric: if (HSSFDateUtil.IsCellDateFormatted(cell2)) { cellType2[i] = "System.DateTime"; } else { try { //DETERMINAR SI ES BOOLEANO if (cell2.CellFormula == "TRUE()") { cellType2[i] = "System.Boolean"; continuar = false; } if (continuar && cell2.CellFormula == "FALSE()") { cellType2[i] = "System.Boolean"; continuar = false; } if (continuar) { cellType2[i] = "System.Double"; continuar = false; } } catch { } } break; } break; default: cellType2[i] = "System.String"; break; } } } //Resolver las diferencias de Tipos if (cellType2[0] == cellType2[1]) { cellType = cellType2[0]; } else { if (cellType2[0] == null) cellType = cellType2[1]; if (cellType2[1] == null) cellType = cellType2[0]; if (cellType == "") cellType = "System.String"; } //Obtener el nombre de la Columna string colName = "Column_{0}"; try { colName = cell.StringCellValue; } catch { colName = string.Format(colName, colIndex); } //Verificar que NO se repita el Nombre de la Columna foreach (DataColumn col in Tabla.Columns) { if (col.ColumnName == colName) colName = string.Format("{0}_{1}", colName, colIndex); } //Agregar el campos de la tabla: DataColumn codigo = new DataColumn(colName, System.Type.GetType(cellType)); Tabla.Columns.Add(codigo); colIndex++; } else { //Las demas filas son registros: switch (cell.CellType) { case CellType.Blank: valorCell = DBNull.Value; break; case CellType.Boolean: valorCell = cell.BooleanCellValue; break; case CellType.String: valorCell = cell.StringCellValue; break; case CellType.Numeric: if (HSSFDateUtil.IsCellDateFormatted(cell)) { valorCell = cell.DateCellValue; } else { valorCell = cell.NumericCellValue; } break; case CellType.Formula: switch (cell.CachedFormulaResultType) { case CellType.Blank: valorCell = DBNull.Value; break; case CellType.String: valorCell = cell.StringCellValue; break; case CellType.Boolean: valorCell = cell.BooleanCellValue; break; case CellType.Numeric: if (HSSFDateUtil.IsCellDateFormatted(cell)) { valorCell = cell.DateCellValue; } else { valorCell = cell.NumericCellValue; } break; } break; default: valorCell = cell.StringCellValue; break; } //Agregar el nuevo Registro if (cell.ColumnIndex <= Tabla.Columns.Count - 1) NewReg[cell.ColumnIndex] = valorCell; } } } if (rowIndex > 0) Tabla.Rows.Add(NewReg); } Tabla.AcceptChanges(); } } else { throw new Exception("ERROR 404: El archivo especificado NO existe."); } } catch (Exception ex) { throw ex; } return Tabla; }
Metode kedua ini melakukan kebalikannya, menyimpan DataTable ke dalam File Excel, ya itu bisa berupa xls atau xlsx baru, pilihan Anda!
/// <summary>Convierte un DataTable en un archivo de Excel (xls o Xlsx) y lo guarda en disco.</summary> /// <param name="pDatos">Datos de la Tabla a guardar. Usa el nombre de la tabla como nombre de la Hoja</param> /// <param name="pFilePath">Ruta del archivo donde se guarda.</param> private void DataTable_To_Excel(DataTable pDatos, string pFilePath) { try { if (pDatos != null && pDatos.Rows.Count > 0) { IWorkbook workbook = null; ISheet worksheet = null; using (FileStream stream = new FileStream(pFilePath, FileMode.Create, FileAccess.ReadWrite)) { string Ext = System.IO.Path.GetExtension(pFilePath); //<-Extension del archivo switch (Ext.ToLower()) { case ".xls": HSSFWorkbook workbookH = new HSSFWorkbook(); NPOI.HPSF.DocumentSummaryInformation dsi = NPOI.HPSF.PropertySetFactory.CreateDocumentSummaryInformation(); dsi.Company = "Cutcsa"; dsi.Manager = "Departamento Informatico"; workbookH.DocumentSummaryInformation = dsi; workbook = workbookH; break; case ".xlsx": workbook = new XSSFWorkbook(); break; } worksheet = workbook.CreateSheet(pDatos.TableName); //<-Usa el nombre de la tabla como nombre de la Hoja //CREAR EN LA PRIMERA FILA LOS TITULOS DE LAS COLUMNAS int iRow = 0; if (pDatos.Columns.Count > 0) { int iCol = 0; IRow fila = worksheet.CreateRow(iRow); foreach (DataColumn columna in pDatos.Columns) { ICell cell = fila.CreateCell(iCol, CellType.String); cell.SetCellValue(columna.ColumnName); iCol++; } iRow++; } //FORMATOS PARA CIERTOS TIPOS DE DATOS ICellStyle _doubleCellStyle = workbook.CreateCellStyle(); _doubleCellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("#,##0.###"); ICellStyle _intCellStyle = workbook.CreateCellStyle(); _intCellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("#,##0"); ICellStyle _boolCellStyle = workbook.CreateCellStyle(); _boolCellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("BOOLEAN"); ICellStyle _dateCellStyle = workbook.CreateCellStyle(); _dateCellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("dd-MM-yyyy"); ICellStyle _dateTimeCellStyle = workbook.CreateCellStyle(); _dateTimeCellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("dd-MM-yyyy HH:mm:ss"); //AHORA CREAR UNA FILA POR CADA REGISTRO DE LA TABLA foreach (DataRow row in pDatos.Rows) { IRow fila = worksheet.CreateRow(iRow); int iCol = 0; foreach (DataColumn column in pDatos.Columns) { ICell cell = null; //<-Representa la celda actual object cellValue = row[iCol]; //<- El valor actual de la celda switch (column.DataType.ToString()) { case "System.Boolean": if (cellValue != DBNull.Value) { cell = fila.CreateCell(iCol, CellType.Boolean); if (Convert.ToBoolean(cellValue)) { cell.SetCellFormula("TRUE()"); } else { cell.SetCellFormula("FALSE()"); } cell.CellStyle = _boolCellStyle; } break; case "System.String": if (cellValue != DBNull.Value) { cell = fila.CreateCell(iCol, CellType.String); cell.SetCellValue(Convert.ToString(cellValue)); } break; case "System.Int32": if (cellValue != DBNull.Value) { cell = fila.CreateCell(iCol, CellType.Numeric); cell.SetCellValue(Convert.ToInt32(cellValue)); cell.CellStyle = _intCellStyle; } break; case "System.Int64": if (cellValue != DBNull.Value) { cell = fila.CreateCell(iCol, CellType.Numeric); cell.SetCellValue(Convert.ToInt64(cellValue)); cell.CellStyle = _intCellStyle; } break; case "System.Decimal": if (cellValue != DBNull.Value) { cell = fila.CreateCell(iCol, CellType.Numeric); cell.SetCellValue(Convert.ToDouble(cellValue)); cell.CellStyle = _doubleCellStyle; } break; case "System.Double": if (cellValue != DBNull.Value) { cell = fila.CreateCell(iCol, CellType.Numeric); cell.SetCellValue(Convert.ToDouble(cellValue)); cell.CellStyle = _doubleCellStyle; } break; case "System.DateTime": if (cellValue != DBNull.Value) { cell = fila.CreateCell(iCol, CellType.Numeric); cell.SetCellValue(Convert.ToDateTime(cellValue)); //Si No tiene valor de Hora, usar formato dd-MM-yyyy DateTime cDate = Convert.ToDateTime(cellValue); if (cDate != null && cDate.Hour > 0) { cell.CellStyle = _dateTimeCellStyle; } else { cell.CellStyle = _dateCellStyle; } } break; default: break; } iCol++; } iRow++; } workbook.Write(stream); stream.Close(); } } } catch (Exception ex) { throw ex; } }
Dengan 2 metode ini Anda dapat membuka file Excel, memuatnya ke dalam DataTable, melakukan modifikasi dan menyimpannya kembali ke dalam file Excel.
Semoga kalian menemukan ini berguna.
sumber
ICSharpCode.SharpZipLib.dll
danNPOI.OpenXmlFormats.dll
juga diperlukan untuk membaca fileSeperti yang ditunjukkan Janoulle, Anda tidak perlu mendeteksi ekstensi mana jika Anda menggunakan WorkbookFactory, itu akan melakukannya untuk Anda. Saya baru-baru ini harus menerapkan solusi menggunakan NPOI untuk membaca file Excel dan mengimpor alamat email ke database sql. Masalah utama saya adalah saya mungkin akan menerima sekitar 12 tata letak Excel yang berbeda dari pelanggan yang berbeda jadi saya membutuhkan sesuatu yang dapat diubah dengan cepat tanpa banyak kode. Saya akhirnya menggunakan Npoi.Mapper yang merupakan alat yang luar biasa! Sangat dianjurkan!
Inilah solusi lengkap saya:
using System.IO; using System.Linq; using Npoi.Mapper; using Npoi.Mapper.Attributes; using NPOI.SS.UserModel; namespace JobCustomerImport.Processors { public class ExcelEmailProcessor { private UserManagementServiceContext DataContext { get; } public ExcelEmailProcessor(int customerNumber) { DataContext = new UserManagementServiceContext(); } public void Execute(string localPath, int sheetIndex) { IWorkbook workbook; using (FileStream file = new FileStream(localPath, FileMode.Open, FileAccess.Read)) { workbook = WorkbookFactory.Create(file); } var importer = new Mapper(workbook); var items = importer.Take<MurphyExcelFormat>(sheetIndex); foreach(var item in items) { var row = item.Value; if (string.IsNullOrEmpty(row.EmailAddress)) continue; UpdateUser(row); } DataContext.SaveChanges(); } private void UpdateUser(MurphyExcelFormat row) { //LOGIC HERE TO UPDATE A USER IN DATABASE... } private class MurphyExcelFormat { [Column("District")] public int District { get; set; } [Column("DM")] public string FullName { get; set; } [Column("Email Address")] public string EmailAddress { get; set; } [Column(3)] public string Username { get; set; } public string FirstName { get { return Username.Split('.')[0]; } } public string LastName { get { return Username.Split('.')[1]; } } } } }
Saya sangat senang dengan NPOI + Npoi.Mapper ( dari Donny Tian ) sebagai solusi impor Excel sehingga saya menulis posting blog tentang hal itu, membahas lebih detail tentang kode ini di atas. Anda dapat membacanya di sini jika Anda ingin: Cara termudah untuk mengimpor file excel . Hal terbaik tentang solusi ini adalah ia berjalan dengan sempurna di lingkungan biru / cloud tanpa server yang tidak bisa saya dapatkan dengan alat / pustaka Excel lainnya.
sumber
private DataTable GetDataTableFromExcel(String Path) { XSSFWorkbook wb; XSSFSheet sh; String Sheet_name; using (var fs = new FileStream(Path, FileMode.Open, FileAccess.Read)) { wb = new XSSFWorkbook(fs); Sheet_name= wb.GetSheetAt(0).SheetName; //get first sheet name } DataTable DT = new DataTable(); DT.Rows.Clear(); DT.Columns.Clear(); // get sheet sh = (XSSFSheet)wb.GetSheet(Sheet_name); int i = 0; while (sh.GetRow(i) != null) { // add neccessary columns if (DT.Columns.Count < sh.GetRow(i).Cells.Count) { for (int j = 0; j < sh.GetRow(i).Cells.Count; j++) { DT.Columns.Add("", typeof(string)); } } // add row DT.Rows.Add(); // write row value for (int j = 0; j < sh.GetRow(i).Cells.Count; j++) { var cell = sh.GetRow(i).GetCell(j); if (cell != null) { // TODO: you can add more cell types capatibility, e. g. formula switch (cell.CellType) { case NPOI.SS.UserModel.CellType.Numeric: DT.Rows[i][j] = sh.GetRow(i).GetCell(j).NumericCellValue; //dataGridView1[j, i].Value = sh.GetRow(i).GetCell(j).NumericCellValue; break; case NPOI.SS.UserModel.CellType.String: DT.Rows[i][j] = sh.GetRow(i).GetCell(j).StringCellValue; break; } } } i++; } return DT; }
sumber
private static ISheet GetFileStream(string fullFilePath) { var fileExtension = Path.GetExtension(fullFilePath); string sheetName; ISheet sheet = null; switch (fileExtension) { case ".xlsx": using (var fs = new FileStream(fullFilePath, FileMode.Open, FileAccess.Read)) { var wb = new XSSFWorkbook(fs); sheetName = wb.GetSheetAt(0).SheetName; sheet = (XSSFSheet) wb.GetSheet(sheetName); } break; case ".xls": using (var fs = new FileStream(fullFilePath, FileMode.Open, FileAccess.Read)) { var wb = new HSSFWorkbook(fs); sheetName = wb.GetSheetAt(0).SheetName; sheet = (HSSFSheet) wb.GetSheet(sheetName); } break; } return sheet; } private static DataTable GetRequestsDataFromExcel(string fullFilePath) { try { var sh = GetFileStream(fullFilePath); var dtExcelTable = new DataTable(); dtExcelTable.Rows.Clear(); dtExcelTable.Columns.Clear(); var headerRow = sh.GetRow(0); int colCount = headerRow.LastCellNum; for (var c = 0; c < colCount; c++) dtExcelTable.Columns.Add(headerRow.GetCell(c).ToString()); var i = 1; var currentRow = sh.GetRow(i); while (currentRow != null) { var dr = dtExcelTable.NewRow(); for (var j = 0; j < currentRow.Cells.Count; j++) { var cell = currentRow.GetCell(j); if (cell != null) switch (cell.CellType) { case CellType.Numeric: dr[j] = DateUtil.IsCellDateFormatted(cell) ? cell.DateCellValue.ToString(CultureInfo.InvariantCulture) : cell.NumericCellValue.ToString(CultureInfo.InvariantCulture); break; case CellType.String: dr[j] = cell.StringCellValue; break; case CellType.Blank: dr[j] = string.Empty; break; } } dtExcelTable.Rows.Add(dr); i++; currentRow = sh.GetRow(i); } return dtExcelTable; } catch (Exception e) { throw; } }
sumber
Karena Anda telah meminta untuk membaca dan mengubah file xls, saya telah mengubah jawaban @ mj82 agar sesuai dengan kebutuhan Anda.
HSSFWorkbook
tidak memilikiSave
metode, tetapi harusWrite
mengalir.static void Main(string[] args) { string filepath = @"C:\test.xls"; HSSFWorkbook hssfwb; using (FileStream file = new FileStream(filepath, FileMode.Open, FileAccess.Read)) { hssfwb = new HSSFWorkbook(file); } ISheet sheet = hssfwb.GetSheetAt(0); for (int row = 0; row <= sheet.LastRowNum; row++) { if (sheet.GetRow(row) != null) //null is when the row only contains empty cells { // Set new cell value sheet.GetRow(row).GetCell(0).SetCellValue("foo"); Console.WriteLine("Row {0} = {1}", row, sheet.GetRow(row).GetCell(0).StringCellValue); } } // Save the file using (FileStream file = new FileStream(filepath, FileMode.Open, FileAccess.Write)) { hssfwb.Write(file); } Console.ReadLine(); }
sumber
Jika Anda tidak ingin menggunakan NPOI.Mapper, saya sarankan Anda untuk memeriksa solusi ini - ini menangani pembacaan sel excel ke dalam berbagai jenis dan juga memiliki pembantu impor sederhana: https://github.com/hidegh/ NPOI. Ekstensi
var data = sheet.MapTo<OrderDetails>(true, rowMapper => { // map singleItem return new OrderDetails() { Date = rowMapper.GetValue<DateTime>(SheetColumnTitles.Date), // use reusable mapper for re-curring scenarios Region = regionMapper(rowMapper.GetValue<string>(SheetColumnTitles.Region)), Representative = rowMapper.GetValue<string>(SheetColumnTitles.Representative), Item = rowMapper.GetValue<string>(SheetColumnTitles.Item), Units = rowMapper.GetValue<int>(SheetColumnTitles.Units), UnitCost = rowMapper.GetValue<decimal>(SheetColumnTitles.UnitCost), Total = rowMapper.GetValue<decimal>(SheetColumnTitles.Total), // read date and total as string, as they're displayed/formatted on the excel DateFormatted = rowMapper.GetValue<string>(SheetColumnTitles.Date), TotalFormatted = rowMapper.GetValue<string>(SheetColumnTitles.Total) }; });
sumber