1

我的表单中有一个 SpreadSheetGear WorkbookView。SpreadSheetGear WorkbookView 已填充 10 行和 10 列的 excel 文件。我想使用下面的代码从单元格中获取数据:

 for (int i = 0; i < cells.Range.RowCount; i++)
 {
   for (int j = 0; j < cells.Range.ColumnCount; j++)
   {
     arrLstWorkBookView.Add(cells[i, j].Text);
     arrLstOutputData.Add(cells[i, j].Text);
   }
 }

并且调试器显示我rowCount = 1048576而不是10, 而rowCount = 16384不是10.

如何解决 WorkbookView 的问题并从 excel 文件中获取正确的行数和列数,行数应为 10,列数应为 10。

4

4 回答 4

5

您没有提供指示cells变量来自何处的代码行,但如果您获得的行数为 1,048,576,这表明我cells来自 IWorksheet。Cells / Range,两者都代表工作表中的所有单元格 (A1:XFD1048576)。

如果您尝试迭代工作表中的某个较小范围,则需要使用IWorksheet.Cells["A1_Ref"]or指定此范围IWorksheet.Cells[row1,col1,row2,col2]。例子:

// The following two lines are equivalent
IRange cells = worksheet.Cells["A1:J10"];
IRange cells = worksheet.Cells[0, 0, 9, 9];
// ...the rest of your code...

如果要遍历工作表的“使用范围”,则需要使用 IWorksheet。使用范围代替。例子:

IRange cells = worksheet.UsedRange;

此外,您在 cells.Range.RowCount 中调用 Range 是多余的,因为 IRange。Range仅表示指定的 IRange。你可以只使用cells.RowCount.

您还可以考虑查看我们的 IRange 索引器文档 (IRange.Item(...)),它演示了引用单元格的多种不同方法: http://www.spreadsheetgear.com/support/help/spreadsheetgear.net。 7.0/#SpreadsheetGear2012.Core~SpreadsheetGear.IRange~Item.html

免责声明:我为 SpreadsheetGear 工作。

于 2013-07-19T14:22:37.957 回答
2

你应该使用

SpreadsheetGear.IRange cells = worksheet.UsedRange;
于 2020-05-15T15:27:21.033 回答
0

获取数据网格的另一种方法是通过数据表,如下所示:

在电子表格名称中的范围

我的表 =Sheet1!$A$1:$J$11

这是 MVC4 / Razor 但它应该转换为 ASP.NET

<!-- language: c# -->
// Declare a DataTable variable
public DataTable myTable;

// Open the workbook.
String filename = HttpContext.Server.MapPath("myspreadsheet.xlsx");
SpreadsheetGear.IWorkbook workbook = SpreadsheetGear.Factory.GetWorkbook(filename);


//Get the table as a dataset:
DataSet dataSet = workbook.GetDataSet("MyTable", SpreadsheetGear.Data.GetDataFlags.FormattedText);
myTable = dataSet.Tables[0];

//Which can also be written as:
myTable = workbook.GetDataSet("MyTable", SpreadsheetGear.Data.GetDataFlags.FormattedText).Tables[0];

在我看来,我用 DataTable 的名称调用局部视图:

@Html.Partial("_DataTable", Model.myTable)

DataTable 部分视图如下所示:

@using System.Data;
@model DataTable
<table>
@{DataRow rowHead = Model.Rows[0];
    <thead>
        <tr>
            @foreach (DataColumn colHead in Model.Columns)       
            {
                <th>@rowHead[colHead.ColumnName]</th> 
             }
        </tr> 
    </thead>
}
    <tbody>
        @{int rowCount = 1;}
        @foreach (DataRow row in Model.Rows)
            {
                <tr>
                    @foreach (DataColumn col in Model.Columns)
                    {
                        <td>@row[col.ColumnName]</td> 
                     }
                </tr>
               rowCount = rowCount + 1;
            } 
    </tbody>
</table>

此代码的一个怪癖是该范围的第一行在表中不可用。其他人需要对此进行解释,但我相信这是因为首先将范围输入 DataSet 并且为列名保留了第一行。也许一些比我更聪明的代码可以在部分视图中提取它。

此示例还显示了如何从电子表格范围呈现 DataTable。

SpreadsheetGear 数据表示例

于 2013-07-21T04:29:51.043 回答
0

除非您确定范围始终为 10x10,在这种情况下,只需更改循环条件,您将需要一种检测连续值的方法。

此代码段应该可以帮助您这样做

/// <summary>
/// gets the number of consecutive (without any empty cell) values vertically
/// </summary>
/// <param name="aRow"></param>
/// <param name="aColumn"></param>
/// <returns></returns>
public int GetNumberConsecValues(int aRow, int aColumn)
{
   int wCount = 0;
   while (this[aRow + wCount, aColumn] != null)
   {
     wCount++;
   }
   return wCount;
}

并根据需要使用它将值读入数组/矩阵:

/// <summary>
/// Reads the vertical array from the specified cell
/// </summary>
/// <param name="aRow"></param>
/// <param name="aColumn"></param>
/// <returns></returns>
public int[] ReadArrayInt(int aRow, int aColumn)
{
  int wNbValues = this.GetNumberConsecValues(aRow, aColumn);
  if (wNbValues == 0)
     return null;

  int[] wArr = new int[wNbValues];
  for (int iRow = 0; iRow < wNbValues; iRow++)
  {
    wArr[iRow] = Convert.ToInt32(this[aRow + iRow, aColumn]);
  }

  return wArr;
}

如果您知道范围,那么您可以使用这个其他代码片段

public object[,] ReadRange(int aColFrom, int aColTo, int aRowFrom, int aRowTo)
{
  this.BeginUpdate();
  try
  {
    SpreadsheetGear.IRange oRange = m_ViewLock.Workbook.ActiveWorksheet.Cells[aRowFrom, aColFrom, aRowTo, aColTo];

    object[,] oValues = new object[aRowTo - aRowFrom + 1, aColTo - aColFrom + 1];

    int iRCol = 0;
    for (int iCol = aColFrom; iCol <= aColTo; iCol++)
    {
      int iRRow = 0;
      for (int iRow = aRowFrom; iRow <= aRowTo; iRow++)
      {
        oValues[iRRow, iRCol] = oRange.Cells[iRRow, iRCol].Value;
        iRRow++;
      }
      iRCol++;
    }
    return oValues;
  }
  finally
  {
    this.EndUpdate();
  }
}

其中 BeginUpdate 和 EndUpdate 定义为:

/// <summary>
/// Must be called before the grid is being modified
/// We also call it inside every method so that if the user forgets to call it is no big deal
/// For this reason the calls can be nested.
/// So if the user forgets to make the call it is safe
/// and if the user does not forget he/she gets the full speed benefits..
/// </summary>
public void BeginUpdate()
{
  if (m_ViewLockCount == 0)
    m_ViewLock = new CWorkbookViewLockHelper(this.Workbook);

  m_ViewLockCount++;
}

/// <summary>
/// Must be called after the grid has being modified
/// </summary>
public void EndUpdate()
{
  m_ViewLockCount--;
  if (m_ViewLockCount <= 0)
  {
    m_ViewLock.Dispose();
    m_ViewLock = null;
  }
}
于 2013-07-18T10:42:13.063 回答