【问题标题】:Selecting a range in a worksheet C#在工作表 C# 中选择范围
【发布时间】:2013-05-11 02:26:43
【问题描述】:

我目前在 Excel 电子表格中打开和阅读以下代码:

var connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=Excel 12.0;", fileNameTextBox.Text);
var queryString = String.Format("SELECT * FROM [{0}]",DETAILS_SHEET_NAME);
var adapter = new OleDbDataAdapter(queryString, connectionString);
var ds = new DataSet();

adapter.Fill(ds, DETAILS_SHEET_NAME);

DataTable data = ds.Tables[DETAILS_SHEET_NAME];

dataGridView1.DataSource = data;
                dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);

这一切都很好,除了我对工作表的第一行(可能是前两行,因为第 2 行是标题)不感兴趣。如何修改选择查询以像在 excel 中一样选择范围?

我有兴趣从 2 开始的所有行中读取包含数据的行中的 A-N 列。

我还需要访问不同工作表上的几个特定单元格,我假设我必须为每个单元格构建另一个具有不同查询字符串的适配器?

【问题讨论】:

  • 请不要在问题标题中重复标签。

标签: c# ole


【解决方案1】:

修改Select 语句,仅包括您需要的列,而不是通配符"*",如下例所示:

("SELECT Column1, Column2 FROM DETAILS_SHEET_NAME");

您可以应用额外的逻辑来删除不必要的行,例如,“分页解决方案”(即选择从 N 到 M 的行),如下所示:

假设数据库表“TBL_ITEM”包含两个感兴趣的列(字段):“Item”列,代表唯一ID和“Rank”,用于升序排序,一般分页问题如下:从按Rank偏移(即跳过)(M-N)行排序的表中选择N行:

SELECT TOP N Item, 
Rank FROM (SELECT TOP M Rank, Item FROM TBL_ITEM ORDER BY Rank) 
AS [SUB_TAB] ORDER BY Rank DESC 

我的文章数据库表分页的纯 SQL 解决方案(链接:http://www.codeproject.com/Tips/441079/Pure-SQL-solution-to-Database-Table-Paging)中彻底讨论了此解决方案及其扩展/示例

最后,您可以使用清单 2 中所示的代码 sn-p 将 DataTable 对象的内容导出到 Excel 文件中,其中包含大量可以添加到代码中的自定义功能;

清单 2. 将 DataTable 导出到 Excel 文件 (2007/2010):

internal static bool Export2Excel(DataTable dataTable, bool Interactive) 
{
    object misValue = System.Reflection.Missing.Value;

    // Note: don't include Microsoft.Office.Interop.Excel in reference (using),
    // it will cause ambiguity w/System.Data: both have DataTable obj
    Microsoft.Office.Interop.Excel.Application _appExcel = null;
    Microsoft.Office.Interop.Excel.Workbook _excelWorkbook = null;
    Microsoft.Office.Interop.Excel.Worksheet _excelWorksheet = null;
    try
    {
        // excel app object
        _appExcel = new Microsoft.Office.Interop.Excel.Application();

        // make it visible to User if Interactive flag is set
        _appExcel.Visible = Interactive;

        // excel workbook object added to app
        _excelWorkbook = _appExcel.Workbooks.Add(misValue);

        _excelWorksheet = _appExcel.ActiveWorkbook.ActiveSheet 
            as Microsoft.Office.Interop.Excel.Worksheet;

        // column names row (range obj)
        Microsoft.Office.Interop.Excel.Range _columnsNameRange;
        _columnsNameRange = _excelWorksheet.get_Range("A1", misValue);
        _columnsNameRange = _columnsNameRange.get_Resize(1, dataTable.Columns.Count);

        // data range obj
        Microsoft.Office.Interop.Excel.Range _dataRange;
        _dataRange = _excelWorksheet.get_Range("A2", misValue);
        _dataRange = _dataRange.get_Resize(dataTable.Rows.Count, dataTable.Columns.Count);

        // column names array to be assigned to columnNameRange
        string[] _arrColumnNames = new string[dataTable.Columns.Count];

        // 2d-array of data to be assigned to _dataRange
        string[,] _arrData = new string[dataTable.Rows.Count, dataTable.Columns.Count];

        // populate both arrays: _arrColumnNames and _arrData
        // note: 2d-array structured as row[idx=0], col[idx=1]
        for (int i = 0; i < dataTable.Columns.Count; i++)
        {
            for (int j = 0; j < dataTable.Rows.Count; j++)
            {
                _arrColumnNames[i] = dataTable.Columns[i].ColumnName;
                _arrData[j, i] = dataTable.Rows[j][i].ToString();
            }
        }

        //assign column names array to _columnsNameRange obj
        _columnsNameRange.set_Value(misValue, _arrColumnNames);

        //assign data array to _dataRange obj
        _dataRange.set_Value(misValue, _arrData);

        // save and close if Interactive flag not set
        if (!Interactive)
        {
            // Excel 2010 - "14.0"
            // Excel 2007 - "12.0"
            string _ver = _appExcel.Version;

            string _fileName ="TableExport_" + 
                DateTime.Today.ToString("yyyy_MM_dd") + "-" +
                DateTime.Now.ToString("hh_mm_ss");

            // check version and select file extension
            if (_ver == "14.0" || _ver == "12.0")  { _fileName += ".xlsx";}
            else { _fileName += ".xls"; }

            // save and close Excel workbook
            _excelWorkbook.Close(true, "{DRIVE LETTER}:\\" + _fileName, misValue);
        }
        return true;
    }
    catch (Exception ex) {  throw; }
    finally
    {
        // quit excel app process
        if (_appExcel != null)
        {
            _appExcel.UserControl = false;
            _appExcel.Quit();
            _appExcel = null;
            misValue = null;
        }
    }
}

【讨论】:

  • 海报指定他们想跳过行而不是列。
  • 我正在为此提供解决方案(引用):“我有兴趣阅读 A-N 列”
  • @Abe Miessler:我只是想知道,你为什么要否决我的回答?我给了你一个合理的解释,还扩展了我的代码来解决第二个问题。 Rgds,
  • 您的第一个答案以及随后对为什么它是合法答案的解释根本不靠谱。很明显,这个问题的重点是确定如何获得位于父集中间的行子集。该帖子确实提到(顺便)他们也想选择特定的列,但如果你建议这是问题,我会说你错了。您的更新似乎确实相关。如果您在答案中包含示例查询,而不是仅仅发布链接,我将撤销我的投票。
  • 好的,我已经用代码 sn-ps 和简要说明修改了我的答案;参考文章中包含详细讨论。 Rgds,
【解决方案2】:

您可以简单地要求没有标题。修改你的连接字符串,添加HDR=No

关于你的第二期,我找到了这个post,也许你会发现它有帮助。

【讨论】:

  • 我不认为前两行是标题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
相关资源
最近更新 更多