eplus를 사용하여 Excel 테이블의 행을 반복하려면 어떻게 해야 합니까?
저는 eplus가 처음이고, 엑셀 테이블에서 몇 가지 가치를 읽으려고 노력하고 있습니다.
지금까지 제가 가진 것은 다음과 같습니다.
var fileInfo = new FileInfo(filename);
using(var excelPackage = new OfficeOpenXml.ExcelPackage(fileInfo))
{
foreach (var sheet in excelPackage.Workbook.Worksheets)
{
foreach (ExcelTable table in sheet.Tables)
{
foreach(var row in table.Rows) // <-- !!
{ ... }
}
}
}
하지만, 지금 저는 당황스럽습니다.ExcelTable
가 있을 뿐입니다.Columns
재산, 하지만 그렇지는 않습니다.Rows
예상했던 대로의 재산찾을 수 없습니다.Rows
라이브러리의 모든 개체에 대한 속성입니다.
행을 행으로 읽으며 표를 반복하려면 어떻게 해야 합니까?
동일한 문제에 대한 도움말을 검색하던 중 이 링크를 우연히 발견했습니다.그것은 확실히 저에게 효과가 있었습니다!Interop 객체를 사용하는 것보다 훨씬 낫습니다.:)
하지만 저는 그것을 약간 조정했습니다:
var package = new ExcelPackage(new FileInfo("sample.xlsx"));
ExcelWorksheet workSheet = package.Workbook.Worksheets[0];
var start = workSheet.Dimension.Start;
var end = workSheet.Dimension.End;
for (int row = start.Row; row <= end.Row; row++)
{ // Row by row...
for (int col = start.Column; col <= end.Column; col++)
{ // ... Cell by cell...
object cellValue = workSheet.Cells[row, col].Text; // This got me the actual value I needed.
}
}
다음과 같이 전체 행을 가져올 수 있는 방법은 다음과 같습니다.ExcelRange
이를 반복하거나 LINQ에 사용할 수 있습니다.
for (var rowNum = 1; rowNum <= sheet.Dimension.End.Row; rowNum++)
{
var row = sheet.Cells[string.Format("{0}:{0}", rowNum)];
// just an example, you want to know if all cells of this row are empty
bool allEmpty = row.All(c => string.IsNullOrWhiteSpace(c.Text));
if (allEmpty) continue; // skip this row
// ...
}
액세스할 수 있습니다..Worksheet
테이블의 속성 및 셀 색인을 지정합니다.이 목적을 위해 열 이름을 셀 값에 매핑하는 일련의 사전을 생성하는 확장 방법을 작성했습니다.
public static IEnumerable<IDictionary<string, object>> GetRows(this ExcelTable table)
{
var addr = table.Address;
var cells = table.WorkSheet.Cells;
var firstCol = addr.Start.Column;
var firstRow = addr.Start.Row;
if (table.ShowHeader)
firstRow++;
var lastRow = addr.End.Row;
for (int r = firstRow; r <= lastRow; r++)
{
yield return Enumerable.Range(0, table.Columns.Count)
.ToDictionary(x => table.Columns[x].Name, x => cells[r, firstCol + x].Value);
}
}
저도 같은 문제가 있었고 그것을 사용하여 해결했습니다.ExcelTable
테이블 경계와 테이블 경계를 가져옵니다.ExcelWorksheet
데이터를 검색합니다.따라서 코드는 다음과 같습니다.
var fileInfo = new FileInfo(filename);
using(var excelPackage = new OfficeOpenXml.ExcelPackage(fileInfo))
{
foreach (var sheet in excelPackage.Workbook.Worksheets)
{
foreach (ExcelTable table in sheet.Tables)
{
ExcelCellAddress start = table.Address.Start;
ExcelCellAddress end = table.Address.End;
for (int row = start.Row; row <= end.Row; ++row)
{
ExcelRange range = sheet.Cells[row, start.Column, row, end.Column];
...
}
}
}
}
표 머리글이나 다른 것들을 확인해야 하는데, 그게 저한테는 도움이 됐어요.
저는 또한 객체를 통해 적절하게 반복하고 이 API로 필요한 데이터를 얻는 방법을 찾고 있었습니다.
저는 다양한 게시물과 저자의 시작 페이지에서 정보를 수집하고 저와 다른 사람들을 돕기 위해 이 모든 것을 정리했습니다.
주요 문제는 반복을 위한 진입점입니다.제가 본 대부분의 솔루션은 워크시트를 따르고 있지만, 이 질문은 표에 구체적으로 나와 있습니다. 저는 두 가지 모두에 대해 궁금했기 때문에 두 가지 모두에 대한 제 연구 결과를 발표합니다.
워크시트 예제:
using (var package = new ExcelPackage(new FileInfo(file)))
{
//what i've seen used the most, entry point is the worksheet not the table w/i the worksheet(s)
using (var worksheet = package.Workbook.Worksheets.FirstOrDefault())
{
if (worksheet != null)
{
for (int rowIndex = worksheet.Dimension.Start.Row; rowIndex <= worksheet.Dimension.End.Row; rowIndex++)
{
var row = worksheet.Row(rowIndex);
//from comments here... https://github.com/JanKallman/EPPlus/wiki/Addressing-a-worksheet
//#:# gets entire row, A:A gets entire column
var rowCells = worksheet.Cells[$"{rowIndex}:{rowIndex}"];
//returns System.Object[,]
//type is string so it likely detects many cells and doesn't know how you want the many formatted together...
var rowCellsText = rowCells.Text;
var rowCellsTextMany = string.Join(", ", rowCells.Select(x => x.Text));
var allEmptyColumnsInRow = rowCells.All(x => string.IsNullOrWhiteSpace(x.Text));
var firstCellInRowWithText = rowCells.Where(x => !string.IsNullOrWhiteSpace(x.Text)).FirstOrDefault();
var firstCellInRowWithTextText = firstCellInRowWithText?.Text;
var firstCellFromRow = rowCells[rowIndex, worksheet.Dimension.Start.Column];
var firstCellFromRowText = firstCellFromRow.Text;
//throws exception...
//var badRow = rowCells[worksheet.Dimension.Start.Row - 1, worksheet.Dimension.Start.Column - 1];
//for me this happened on row1 + row2 beign merged together for the column headers
//not sure why the row.merged property is false for both rows though
if (allEmptyColumnsInRow)
continue;
for (int columnIndex = worksheet.Dimension.Start.Column; columnIndex <= worksheet.Dimension.End.Column; columnIndex++)
{
var column = worksheet.Column(columnIndex);
var currentRowColumn = worksheet.Cells[rowIndex, columnIndex];
var currentRowColumnText = currentRowColumn.Text;
var currentRowColumnAddress = currentRowColumn.Address;
//likely won't need to do this, but i wanted to show you can tangent off at any level w/ that info via another call
//similar to row, doing A:A or B:B here, address is A# so just get first char from address
var columnCells = worksheet.Cells[$"{currentRowColumnAddress[0]}:{currentRowColumnAddress[0]}"];
var columnCellsTextMany = string.Join(", ", columnCells.Select(x => x.Text));
var allEmptyRowsInColumn = columnCells.All(x => string.IsNullOrWhiteSpace(x.Text));
var firstCellInColumnWithText = columnCells.Where(x => !string.IsNullOrWhiteSpace(x.Text)).FirstOrDefault();
var firstCellInColumnWithTextText = firstCellInColumnWithText?.Text;
}
}
}
}
}
이제 여기서 일이 좀 꼬일 수 있습니다. 적어도 저에게는 처음부터 테이블이 없었습니다.동일한 패키지 사용 문에서 먼저 워크시트 셀 위에 반복한 다음 Tables 속성이 있는 모든 것을 터치하면 예외가 발생합니다.패키지를 다시 인스턴스화하고 동일한/유사한 코드를 사용하는 경우 테이블이 있는지 확인할 때 폭발하지 않습니다.
표 예:
//for some reason, if i don't instantiating another package and i work with the 'Tables' property in any way, the API throws a...
//Object reference not set to an instance of an object.
//at OfficeOpenXml.ExcelWorksheet.get_Tables()
//excetion... this is because i have data in my worksheet but not an actual 'table' (Excel => Insert => Table)
//a parital load of worksheet cell data + invoke to get non-existing tables must have a bug as below code does not
//throw an exception and detects null gracefully on firstordefault
using (var package = new ExcelPackage(new FileInfo(file)))
{
//however, question was about a table, so lets also look at that... should be the same?
//no IDisposable? :(
//adding a table manually to my worksheet allows the 'same-ish' (child.Parent, aka table.WorkSheet) code to iterate
var table = package.Workbook.Worksheets.SelectMany(x => x.Tables).FirstOrDefault();
if (table != null)
{
for (int rowIndex = table.Address.Start.Row; rowIndex <= table.Address.End.Row; rowIndex++)
{
var row = table.WorkSheet.Row(rowIndex);
var rowCells = table.WorkSheet.Cells[$"{rowIndex}:{rowIndex}"];
var rowCellsManyText = string.Join(", ", rowCells.Select(x => x.Text));
for (int columnIndex = table.Address.Start.Column; columnIndex <= table.Address.End.Column; columnIndex++)
{
var currentRowColumn = table.WorkSheet.Cells[rowIndex, columnIndex];
var currentRowColumnText = currentRowColumn.Text;
}
}
}
}
기본적으로 모든 것이 동일한 방식으로 작동하고 작동합니다. 단지 아이를 돌봐야 합니다.부모, 별칭 표.워크시트를 사용하여 동일한 작업을 수행할 수 있습니다.다른 사람들이 언급했듯이 확장 방법과 래퍼 클래스를 사용하면 비즈니스 요구 사항의 세부 사항에 따라 보다 세분화할 수 있지만 이 질문의 목적은 아닙니다.
인덱싱 의견 및 응답과 관련하여 하드 코딩 인덱스 대 인덱싱되지 않은 기본 속성 대신 '행' 및 '열' 속성을 유지하는 것이 좋습니다. 적어도 새 버전에서는 문제가 없었습니다.
eplus는 잘 모르겠지만, 저는 LinkQToExcel을 사용하는 것에 대해 빠르게 제안할 것이라고 생각했습니다.
var excel = new ExcelQueryFactory(excel);
var info = excel.Worksheet("Sheet1")
.Select(z=> new
{
Name = row["Name"].Cast<string>(),
Age = row["Age"].Cast<int>(),
}).ToList();
NuGet에서 얻을 수 있습니다.
Install-Package LinqToExcel
언급URL : https://stackoverflow.com/questions/21742038/how-do-i-iterate-through-rows-in-an-excel-table-using-epplus
'source' 카테고리의 다른 글
MongoDB에서 초기 데이터를 로드하는 방법은 무엇입니까? (0) | 2023.07.08 |
---|---|
엔티티 프레임워크가 ID 열을 삽입하도록 강제하려면 어떻게 해야 합니까? (0) | 2023.07.08 |
DOKER Spring Boot에 env 변수 전달 (0) | 2023.07.08 |
Angular Material 2 테이블 서버 측면 페이지 (0) | 2023.07.03 |
dplyr을 사용한 data.frame의 전체 사례 필터(대소문자별 삭제) (0) | 2023.07.03 |