NPOI를 사용하여 파일을 읽는 방법입니다.
NPOI는 C#으로 Excel 파일을 작성하기에 매우 좋다는 것을 알았습니다.
하지만 저는 C#에서 엑셀 파일을 열고 읽고 수정하고 싶습니다.
이거 어떻게 해요?
아래의 간단한 읽기 예는 다음과 같습니다.
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));
}
}
}
참고로, 여기 다운로드 섹션의 NPOI 웹 사이트에는 C# 예제 팩인 예제 패키지가 있습니다.아직 안 드셨다면 드셔보세요.:)
워크북 팩토리를 사용하여 워크북 개체를 인스턴스화하면 공장 방법에서 xls 또는 xlsx를 탐지할 수 있으므로 도움이 될 수 있습니다.참조 자료: http://apache-poi.1045710.n5.nabble.com/How-to-check-for-valid-excel-files-using-POI-without-checking-the-file-extension-td2341055.html
IWorkbook workbook = WorkbookFactory.Create(inputStream);
시트의 이름은 모르지만 색인(0 기준)은 확실하다면 다음과 같이 시트를 잡을 수 있습니다.
ISheet sheet = workbook.GetSheetAt(sheetIndex);
그런 다음 mj82에서 수락한 답변에 의해 제공된 코드를 사용하여 행을 반복할 수 있습니다.
NPOI가 Excel 파일 작업에 매우 유용하다고 생각합니다. 구현 내용은 다음과 같습니다(댓글은 스페인어입니다. 죄송합니다).
이 방법 Excel(xls 또는 xlsx 모두) 파일을 열고 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;
}
이 두 번째 방법은 데이터 테이블을 Excel 파일에 저장합니다. 예, xls 또는 새 xlsx 중 하나를 선택할 수 있습니다!
/// <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;
}
}
이 두 가지 방법으로 Excel 파일을 열고 DataTable에 로드하고 수정한 후 Excel 파일에 다시 저장할 수 있습니다.
이게 쓸모있기를 바랍니다.
Janoulle이 지적했듯이 WorkbookFactory를 사용하면 어떤 내선 번호인지 감지할 필요가 없습니다.최근에 Excel 파일을 읽고 이메일 주소를 SQL 데이터베이스로 가져오기 위해 NPOI를 사용하는 솔루션을 구현해야 했습니다.저의 주된 문제는 아마도 12개의 다른 고객들로부터 엑셀 레이아웃을 받게 될 것이기 때문에 코드 없이 빠르게 변경할 수 있는 것이 필요했다는 것입니다.Npoi를 쓰게 되었습니다.Mapper는 정말 멋진 도구입니다!강력추천합니다!
완벽한 솔루션은 다음과 같습니다.
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];
}
}
}
}
}
NPOI+NPOI가 너무 좋아요.Excel Import 솔루션으로 Mapper(Donny Tian)를 사용하여 블로그에 게시했습니다. 위의 코드에 대해 자세히 설명합니다.원하는 경우 여기에서 읽을 수 있습니다. Excel 파일을 가져오는 가장 쉬운 방법입니다.이 솔루션의 가장 좋은 점은 다른 Excel 툴/라이브러리에서는 얻을 수 없었던 서버 없는 Azure/클라우드 환경에서 완벽하게 실행된다는 것입니다.
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;
}
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;
}
}
당신이 xls 파일을 읽고 수정해 달라고 요청했기 때문에, 나는 당신의 요구에 맞게 @mj82의 답변을 변경했습니다.
HSSFWorkbook이 없습니다.Save방법은 있지만 방법은 있습니다.Write네, 그렇습니다.
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();
}
NPOI를 사용하지 않으려면 선택하십시오.매퍼, 그렇다면 이 솔루션을 확인해 보시기 바랍니다. 다양한 유형의 엑셀 셀을 읽을 수 있고 간단한 가져오기 도우미도 있습니다. https://github.com/hidegh/NPOI.Extensions
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)
};
});
언급URL : https://stackoverflow.com/questions/5855813/how-to-read-file-using-npoi 입니다.
'programing' 카테고리의 다른 글
| C# 구분 기호가 있는 문자열에 대한 목록입니다. (0) | 2023.04.25 |
|---|---|
| UNIX 내보내기 명령입니다. (0) | 2023.04.25 |
| Base64 문자열을 디코딩하려면 어떻게 해야 합니까? (0) | 2023.04.25 |
| HTML 표를 Excel에 붙여넣습니다. 줄 바꿈을 셀에 유지하는 방법 (0) | 2023.04.25 |
| Android SQLite에서 날짜를 사용하는 가장 좋은 방법입니다. (0) | 2023.04.25 |