Как вставить строки в объект таблицы внутри листа Excel?

У меня возникают трудности с вставкой строк в существующий объект таблицы. Вот мой фрагмент кода:

string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + @"C:\myExcelFile.xlsx" + ";Extended Properties=\"Excel 12.0;ReadOnly=False;HDR=Yes;\"";
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
    conn.Open();
    OleDbCommand cmd = new OleDbCommand();
    cmd.Connection = conn;

    string insertQuery = String.Format("Insert into [{0}$] (ID, Title,NTV_DB, Type ) values(7959, 8,'e','Type1')", TabDisplayName);
    cmd.CommandText = insertQuery;
    cmd.ExecuteNonQuery();
    cmd = null;
    conn.Close();
}

В результате я получаю свои строки, вставленные под готовым табличным объектом:

enter image description here

Я также попытался вставить данные внутри объекта таблицы следующим образом:

 string insertQuery = String.Format("Insert into [{0}$].[MyTable] (ID, Title,NTV_DB, Type ) values(7959, 8,'e','Type1')", TabDisplayName);

Но я получаю сообщение об ошибке:

Механизм базы данных Microsoft Access не смог найти объект "MyTable". Убедитесь, что объект существует, и вы правильно назовете его имя и имя пути. Если "MyTable" не является локальным объектом, проверьте сетевое подключение или обратитесь к администратору сервера.

Как вы можете видеть, таблица с именем MyTable существует. Я был бы очень благодарен, если кто-то может пролить свет на эту тайну.

enter image description here

Ответы

Ответ 1

На основе здесь:

ADO.NET не может обращаться к объектам XL Table (aka Lists) и не может получить доступ которые прямо или косвенно ссылаются на имя таблицы или структурированные ссылки. ADO.NET может обращаться к именованным диапазонам по таблицам которые ссылаются на диапазон ячеек таблицы.

Пример: Имя MyTable относится к =$A$1:$E$3. Таким образом, для этой цели вы можете использовать Range например (Sheet1$A:E). В этом случае ваш оператор Insert может измениться на следующее:

string insertQuery = "INSERT INTO [Sheet1$A:E] (ID, Title,NTV_DB, Type) VALUES (7959, 8,'e','Type1')"; 

Другие ограничения:

Защита рабочей книги: ADO не может получить доступ к защищенным паролем учебникам.

Используемые строки: ADO будет вставляться ниже последней используемой строки. ЗАМЕТКА! Последняя используемая строка может быть пустой.

И Tables, как уже упоминалось.

Ответ 2

Если вы выполните этот код:

var contents = new DataTable();
using (OleDbDataAdapter adapter = new OleDbDataAdapter(string.Format("Select * From [{0}$]", TabDisplayName), conn))
{
    adapter.Fill(contents);
}
Console.WriteLine(contents.Rows.Count);//7938

вы увидите 7938 (номер последней строки на снимке экрана). И когда вы вставляете новую строку, она вставлена ​​в позицию 7939. Пустое содержимое в (7929, 7930,...) строках игнорируется, потому что excel знает, что последнее число - 7938.

Решения:

  • Вы должны удалить все строки после 7928 в файле excel.
  • Вы должны вставить определенную позицию.

Ответ 3

Если вы используете поставщик Microsoft.ACE.OLEDB, тогда имейте в виду, что он не поддерживает именованный диапазон. Вам нужно указать имя листа [Sheet1$] или имя листа, за которым следует диапазон [Sheet1$A1:P7928]. Если диапазон не указан, он будет определять таблицу как используемый диапазон, который может содержать пустые строки.

Один из способов обработки пустых строк - удалить их, но драйвер не поддерживает операцию DELETE.

Другой способ - сначала подсчитать количество строк с непустым Id, а затем использовать результат для определения диапазона таблицы для оператора INSERT:

using (OleDbConnection conn = new OleDbConnection(connectionString)) {
    conn.Open();

    string SheetName = "Sheet1";
    string TableRange = "A1:P{0}";

    // count the number of non empty rows
    using (var cmd1 = new OleDbCommand(null, conn)) {
        cmd1.CommandText = String.Format(
          "SELECT COUNT(*) FROM [{0}$] WHERE ID IS NOT NULL;"
          , SheetName);

        TableRange = string.Format(TableRange, (int)cmd1.ExecuteScalar() + 1);
    }

    // insert a new record
    using (var cmd2 = new OleDbCommand(null, conn)) {
        cmd2.CommandText = String.Format(
            "INSERT INTO [{0}${1}] (ID, Title, NTV_DB, Type) VALUES(7959, 8,'e','Type1');"
            , SheetName, TableRange);

        cmd2.ExecuteNonQuery();
    }
}

Ответ 4

Попробуйте это

private void GetExcelSheets(string FilePath, string Extension, string isHDR)
{
string conStr="";
switch (Extension)
{
    case ".xls": //Excel 97-03
        conStr = ConfigurationManager.ConnectionStrings["Excel03ConString"]
                 .ConnectionString;
        break;
    case ".xlsx": //Excel 07
        conStr = ConfigurationManager.ConnectionStrings["Excel07ConString"]
                 .ConnectionString;
        break;
}

//Get the Sheets in Excel WorkBoo
conStr = String.Format(conStr, FilePath, isHDR);
OleDbConnection connExcel = new OleDbConnection(conStr);
OleDbCommand cmdExcel = new OleDbCommand();
OleDbDataAdapter oda = new OleDbDataAdapter();
cmdExcel.Connection = connExcel;
connExcel.Open();

//Bind the Sheets to DropDownList
ddlSheets.Items.Clear(); 
ddlSheets.Items.Add(new ListItem("--Select Sheet--", ""));    
ddlSheets.DataSource=connExcel
         .GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
ddlSheets.DataTextField = "TABLE_NAME";
ddlSheets.DataValueField = "TABLE_NAME";
ddlSheets.DataBind();
connExcel.Close();
txtTable.Text = "";
lblFileName.Text = Path.GetFileName(FilePath);
Panel2.Visible = true;
Panel1.Visible = false;
}

Ответ 5

Я не уверен, что Access С# работает так же, как и Excel, но для меня это работало в электронной таблице. Может быть, это может вам помочь?

Table3.ListRows[1].Range.Insert(Excel.XlInsertShiftDirection.xlShiftDown);