内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用
我正在尝试使用互操作库从Excel文件中删除所有额外的空白行和列。
但是,我有excel文件,其中包含一小组数据,但是有很多空行和列。(从最后一个非空行(或列)到工作表的末尾)
我试着遍历行和列,但是循环需要几个小时。
我正在尝试获取最后一个非空行和列索引,以便在一行中删除整个空范围。
XlWks.Range("...").EntireRow.Delete(xlShiftUp)
注意:我正在尝试获取包含数据的最后一行,以删除所有额外的空白(在此行或列之后)。
有什么建议吗?
可以使用下面的代码获取索引小于最后一个空行的最后非空行
List<int> NonEmptyRows = Enumerable.Range(1, rowsToDelete.Max()).ToList().Except(rowsToDelete).ToList();
如果NonEmptyRows.Max() < rowsToDelete.Max()
最后一个非空行是NonEmptyRows.Max()
否则就是worksheet.Rows.Count
最后一次使用后没有空行。
同样的方法可以得到最后一个非空列。
代码是在DeleteCols
和DeleteRows
职能:
private static void DeleteRows(List<int> rowsToDelete, Microsoft.Office.Interop.Excel.Worksheet worksheet) { // the rows are sorted high to low - so index's wont shift List<int> NonEmptyRows = Enumerable.Range(1, rowsToDelete.Max()).ToList().Except(rowsToDelete).ToList(); if (NonEmptyRows.Max() < rowsToDelete.Max()) { // there are empty rows after the last non empty row Microsoft.Office.Interop.Excel.Range cell1 = worksheet.Cells[NonEmptyRows.Max() + 1,1]; Microsoft.Office.Interop.Excel.Range cell2 = worksheet.Cells[rowsToDelete.Max(), 1]; //Delete all empty rows after the last used row worksheet.Range[cell1, cell2].EntireRow.Delete(Microsoft.Office.Interop.Excel.XlDeleteShiftDirection.xlShiftUp); } //else last non empty row = worksheet.Rows.Count foreach (int rowIndex in rowsToDelete.Where(x => x < NonEmptyRows.Max())) { worksheet.Rows[rowIndex].Delete(); } } private static void DeleteCols(List<int> colsToDelete, Microsoft.Office.Interop.Excel.Worksheet worksheet) { // the cols are sorted high to low - so index's wont shift //Get non Empty Cols List<int> NonEmptyCols = Enumerable.Range(1, colsToDelete.Max()).ToList().Except(colsToDelete).ToList(); if (NonEmptyCols.Max() < colsToDelete.Max()) { // there are empty rows after the last non empty row Microsoft.Office.Interop.Excel.Range cell1 = worksheet.Cells[1,NonEmptyCols.Max() + 1]; Microsoft.Office.Interop.Excel.Range cell2 = worksheet.Cells[1,NonEmptyCols.Max()]; //Delete all empty rows after the last used row worksheet.Range[cell1, cell2].EntireColumn.Delete(Microsoft.Office.Interop.Excel.XlDeleteShiftDirection.xlShiftToLeft); } //else last non empty column = worksheet.Columns.Count foreach (int colIndex in colsToDelete.Where(x => x < NonEmptyCols.Max())) { worksheet.Columns[colIndex].Delete(); } }
几年前,我创建了一个MSDN代码示例,允许开发人员从工作表中获取最后使用的行和列。我修改了它,将所有需要的代码放在一个带有windows表单前端的类库中,以演示操作。
底层代码使用Microsoft.Office.Interop.Excel。
在这里,我得到Excel文件中的第一个工作表,得到最后使用的行和行,并将其作为有效的单元格地址呈现。
Private Sub cmdAddress1_Click(sender As Object, e As EventArgs) Handles cmdAddress1.Click Dim ops As New GetExcelColumnLastRowInformation Dim info = New UsedInformation ExcelInformationData = info.UsedInformation(FileName, ops.GetSheets(FileName)) Dim SheetName As String = ExcelInformationData.FirstOrDefault.SheetName Dim cellAddress = ( From item In ExcelInformationData Where item.SheetName = ExcelInformationData.FirstOrDefault.SheetName Select item.LastCell).FirstOrDefault MessageBox.Show($"{SheetName} - {cellAddress}") End Sub
在演示项目中,我还获得了Excel文件的所有工作表,并将它们显示在ListBox中。从列表框中选择工作表名称,并在有效的单元格地址中获取工作表的最后一行和列。
Private Sub cmdAddress_Click(sender As Object, e As EventArgs) Handles cmdAddress.Click Dim cellAddress = ( From item In ExcelInformationData Where item.SheetName = ListBox1.Text Select item.LastCell).FirstOrDefault If cellAddress IsNot Nothing Then MessageBox.Show($"{ListBox1.Text} {cellAddress}") End If End Sub
从上面的链接打开解决方案的第一眼,你就会注意到有很多代码。代码是最优的,并将立即释放所有对象。