gpt4 book ai didi

c# - 如何读取 Excel 电子表格中的单个列?

转载 作者:行者123 更新时间:2023-11-30 15:23:36 25 4
gpt4 key购买 nike

我正在尝试从 Excel 文档中读取单个列。我想阅读整个专栏,但显然只存储有数据的单元格。我还想尝试处理这种情况,即列中的单元格为空,但如果列中的下方有内容,它将读取后面的单元格值。例如:

| Column1 |
|---------|
|bob |
|tom |
|randy |
|travis |
|joe |
| |
|jennifer |
|sam |
|debby |

如果我有该列,我不介意 joe 之后的行的值为 "",但我确实希望它在之后继续获取值空白单元格。但是,假设 debby 是列中的最后一个值,我不希望它在 debby 之后继续 35,000 行。

也可以安全地假设这将始终是第一列。

到目前为止,我有这个:

Excel.Application myApplication = new Excel.Application();
myApplication.Visible = true;
Excel.Workbook myWorkbook = myApplication.Workbooks.Open("C:\\aFileISelect.xlsx");
Excel.Worksheet myWorksheet = myWorkbook.Sheets["aSheet"] as Excel.Worksheet;
Excel.Range myRange = myWorksheet.get_Range("A:A", Type.Missing);

foreach (Excel.Range r in myRange)
{
MessageBox.Show(r.Text);
}

我从旧版本的 .NET 中找到了很多做类似事情的例子,但不完全是这个,我想确保我做的事情更现代(假设人们用来做这件事的方法已经改变了一些金额)。

我当前的代码读取整列,但在最后一个值之后包含空白单元格。


编辑1

我喜欢下面 Isedlacek 的回答,但我确实有一个问题,我不确定是否特定于他的代码。如果我这样使用它:

Excel.Application myApplication = new Excel.Application();
myApplication.Visible = true;
Excel.Workbook myWorkbook = myApplication.Workbooks.Open("C:\\aFileISelect.xlsx");
Excel.Worksheet myWorksheet = myWorkbook.Sheets["aSheet"] as Excel.Worksheet;
Excel.Range myRange = myWorksheet.get_Range("A:A", Type.Missing);

var nonEmptyRanges = myRange.Cast<Excel.Range>()
.Where(r => !string.IsNullOrEmpty(r.Text));

foreach (var r in nonEmptyRanges)
{
MessageBox.Show(r.Text);
}

MessageBox.Show("Finished!");

Finished! MessageBox 永远不会显示。我不确定为什么会这样,但它似乎从未真正完成搜索。我尝试在循环中添加一个计数器,看看它是否只是在连续搜索列,但它似乎并没有……它似乎只是停止了。

Finished! MessageBox 所在的位置,我试图关闭工作簿和电子表格,但该代码从未运行(正如预期的那样,因为 MessageBox 从未运行过)。

如果我手动关闭 Excel 电子表格,我会收到 COMException:

COMException was unhandled by user code
Additional information: Exception from HRESULT: 0x803A09A2

有什么想法吗?

最佳答案

答案取决于您是要获取所用单元格的边界范围还是要从列中获取非空值。

下面介绍了如何有效地从列中获取非空值。请注意,一次读取整个 tempRange.Value 属性比逐个单元格读取快 MUCH,但代价是生成的数组会占用大量内存.

private static IEnumerable<object> GetNonNullValuesInColumn(_Application application, _Worksheet worksheet, string columnName)
{
// get the intersection of the column and the used range on the sheet (this is a superset of the non-null cells)
var tempRange = application.Intersect(worksheet.UsedRange, (Range) worksheet.Columns[columnName]);

// if there is no intersection, there are no values in the column
if (tempRange == null)
yield break;

// get complete set of values from the temp range (potentially memory-intensive)
var value = tempRange.Value2;

// if value is NULL, it's a single cell with no value
if (value == null)
yield break;

// if value is not an array, the temp range was a single cell with a value
if (!(value is Array))
{
yield return value;
yield break;
}

// otherwise, the value is a 2-D array
var value2 = (object[,]) value;
var rowCount = value2.GetLength(0);
for (var row = 1; row <= rowCount; ++row)
{
var v = value2[row, 1];
if (v != null)
yield return v;
}
}

这是获取列中包含非空单元格的最小范围的有效方法。请注意,我仍然一次读取整组 tempRange 值,然后使用生成的数组(如果是多单元格范围)来确定哪些单元格包含第一个和最后一个值。然后在找出哪些行有数据后构建边界范围。

private static Range GetNonEmptyRangeInColumn(_Application application, _Worksheet worksheet, string columnName)
{
// get the intersection of the column and the used range on the sheet (this is a superset of the non-null cells)
var tempRange = application.Intersect(worksheet.UsedRange, (Range) worksheet.Columns[columnName]);

// if there is no intersection, there are no values in the column
if (tempRange == null)
return null;

// get complete set of values from the temp range (potentially memory-intensive)
var value = tempRange.Value2;

// if value is NULL, it's a single cell with no value
if (value == null)
return null;

// if value is not an array, the temp range was a single cell with a value
if (!(value is Array))
return tempRange;

// otherwise, the temp range is a 2D array which may have leading or trailing empty cells
var value2 = (object[,]) value;

// get the first and last rows that contain values
var rowCount = value2.GetLength(0);
int firstRowIndex;
for (firstRowIndex = 1; firstRowIndex <= rowCount; ++firstRowIndex)
{
if (value2[firstRowIndex, 1] != null)
break;
}
int lastRowIndex;
for (lastRowIndex = rowCount; lastRowIndex >= firstRowIndex; --lastRowIndex)
{
if (value2[lastRowIndex, 1] != null)
break;
}

// if there are no first and last used row, there is no used range in the column
if (firstRowIndex > lastRowIndex)
return null;

// return the range
return worksheet.Range[tempRange[firstRowIndex, 1], tempRange[lastRowIndex, 1]];
}

关于c# - 如何读取 Excel 电子表格中的单个列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34272678/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com