使用OLEDB更新Excel单元格

时间:2018-02-27 21:08:44

标签: excel oledb

我想使用OLEDB更新Excel(xlsx)文件中的1个单元格。 我附上了我的代码。 第一次运行时,它会填充值,因为INSERT正在运行。 第二次运行时,它会附加值,因为UPDATE失败,我的Catch执行INSERT。我的目标是让UPDATE命令工作。执行UPDATE命令时,出现错误消息:

没有给出一个或多个必需参数的值。    在System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr)    在System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams,Object& executeResult)    在System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult)    在System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior,Object& executeResult)    在System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior,String method)    在System.Data.OleDb.OleDbCommand.ExecuteNonQuery()    在ConsoleApp3.Program.InsertCSVIntoSheet(String excelPath,String sheet,String csvPath)中的C:\ Users \ jbendler.atlab \ source \ repos \ ConsoleApp3 \ Program.cs:第175行

此代码来自演示控制台应用程序。这是program.cs文件。 代码的主要部分位于InsertCSVIntoSheet方法的底部。输出xlsx文件只是一个未编辑的新工作簿。输入文件只是一个文本文件,以.csv扩展名命名,包含以下由car-return / linefeed分隔的内容 - 因此文件有5行,每行一个字符:

  • A
  • C
  • d
  • 电子
  • 感谢。

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.OleDb;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Transactions;
    
    namespace ConsoleApp3
    {
    class Program
    {
        static void Main(string[] args)
        {
            InsertCSVIntoSheet(@"c:\temp\book1.xlsx", "NewSheet", @"c:\temp\test.csv");
        }
    
        private static void InsertCSVIntoSheet(string excelPath, string sheet, string csvPath)
        {
            int column;
            int row;
            int pos;
            bool done;
            char readUntilChar;
            string csvData;
            string columnName;
            string cell;
            string excelSheetName;
            List<Tuple<int, int, object>> values = new List<Tuple<int, int, object>>();
            string connectionString = CreateOleDbConnectionStringForExcel(excelPath);
            OleDbCommand oleDbCommand = new OleDbCommand();
            decimal decimalTest;
            DateTime dateTimeTest;
            int status;
            int numColumns;
    
            // Put CSV in to row/column/value Tuples
            using (StreamReader reader = new StreamReader(csvPath))
            {
                csvData = reader.ReadToEnd();
                row = 1;
    
                // Split the csv data by new line
                foreach (string line in csvData.Split(new string[] { "\r\n" }, StringSplitOptions.None))
                {
                    if (!string.IsNullOrEmpty(line))
                    {
                        column = 1;
                        pos = 0;
                        cell = string.Empty;
    
                        // Split each line by ',' to get each cell.  A value wrapped in '"' can include a ','
                        while (pos < line.Length)
                        {
                            cell = string.Empty;
    
                            // Check the first character.  If it is a '"' then we assume the cell is surrounded
                            //   in '"' and do NOT include the '"' in the output to the excel cell.
                            if (line[pos] == '"')
                            {
                                readUntilChar = '"';
                                pos++;
                            }
                            else
                            {
                                readUntilChar = ',';
                            }
    
                            done = line[pos] == readUntilChar;
    
                            if (line[pos] == '"')
                            {
                                // Skip over second '"' for a blank ("")
                                pos++;
                            }
    
                            while (!done)
                            {
                                cell += line[pos++];
    
                                if (pos == line.Length || line[pos] == readUntilChar)
                                {
                                    if (readUntilChar == '"')
                                    {
                                        // Skip the '"'
                                        pos++;
                                    }
    
                                    done = true;
                                }
                            }
    
                            // Skip over the ','
                            pos++;
    
                            if (!string.IsNullOrEmpty(cell))
                            {
                                // Test the data to determine the type (check for decimal and DateTime).
                                if (decimal.TryParse(cell, out decimalTest))
                                {
                                    values.Add(new Tuple<int, int, object>(row, column, decimalTest));
                                }
                                else if (DateTime.TryParse(cell, out dateTimeTest))
                                {
                                    values.Add(new Tuple<int, int, object>(row, column, dateTimeTest));
                                }
                                else
                                {
                                    // Write out the value as a string
                                    values.Add(new Tuple<int, int, object>(row, column, cell));
                                }
                            }
    
                            column++;
                        }
                    }
    
                    row++;
                }
            }
    
            using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Suppress))
            {
                excelSheetName = GetExcelSheetNames(connectionString).Where(n => n.ToUpper().StartsWith(sheet.ToUpper())).FirstOrDefault();
    
                //Set the connection string to recognize the header and to operate in Update mode(IMEX= 0)
                using (OleDbConnection oleDbConnection = new OleDbConnection(connectionString.Replace("IMEX=1", "IMEX=0")))
                {
                    oleDbConnection.Open();
    
                    oleDbCommand = new OleDbCommand();
                    oleDbCommand.Connection = oleDbConnection;
                    oleDbCommand.CommandType = CommandType.Text;
    
                    if (excelSheetName != null)
                    {
                        // Delete Sheet
                        oleDbCommand.CommandText = "DROP TABLE [" + sheet + "]";
                        status = oleDbCommand.ExecuteNonQuery();
                    }
                    else
                    {
                        excelSheetName = sheet + "$";
                    }
    
                    numColumns = values.Max(v => v.Item2);
    
                    oleDbCommand.CommandText = "CREATE TABLE [" + sheet + "](";
    
                    for (int index = 0; index < numColumns; index++)
                    {
                        oleDbCommand.CommandText += "Column" + index.ToString() + " CHAR(255), ";
                    }
    
                    oleDbCommand.CommandText = oleDbCommand.CommandText.Substring(0, oleDbCommand.CommandText.Length - 2) + ")";
    
                    status = oleDbCommand.ExecuteNonQuery();
                }
    
                using (OleDbConnection oleDbConnection = new OleDbConnection(connectionString.Replace("IMEX=1", "IMEX=0")))
                {
                    oleDbConnection.Open();
                    oleDbCommand.Connection = oleDbConnection;
    
                    // Write out new values
                    foreach (Tuple<int, int, object> tuple in values)
                    {
                        try
                        {
                            columnName = GetExcelColumnName(tuple.Item2) + (tuple.Item1 + 1).ToString();
    
                            oleDbCommand.CommandText = "UPDATE [" + excelSheetName + columnName + ":" + columnName + "] SET " + "F1" + " = '" + tuple.Item3.ToString() + "'";
                            status = oleDbCommand.ExecuteNonQuery();
                        }
                        catch (OleDbException oledbex)
                        {
                            oleDbCommand.CommandText = "INSERT INTO [" + excelSheetName + "] VALUES ('" + tuple.Item3.ToString() + "')";
                            status = oleDbCommand.ExecuteNonQuery();
                        }
                    }
                }
            }
        }
    
        private static List<string> GetExcelSheetNames(string connectionString)
        {
            OleDbConnection oleDbConnection = null;
            DataTable dataTable = null;
            List<string> excelSheetNames = null;
    
            using (oleDbConnection = new OleDbConnection(connectionString))
            {
                oleDbConnection.Open();
                dataTable = oleDbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
            }
    
            if (dataTable != null)
            {
                excelSheetNames = new List<string>(dataTable.Rows.Cast<DataRow>().Where(r => r["TABLE_NAME"].ToString().EndsWith("$") || r["TABLE_NAME"].ToString().EndsWith("$'")).Select(r => r["TABLE_NAME"].ToString().ToUpper()));
            }
    
            return excelSheetNames;
        }
    
        private static string CreateOleDbConnectionStringForExcel(string sourceFile)
        {
            var fileInfo = new FileInfo(sourceFile);
    
            switch (fileInfo.Extension.ToUpper())
            {
    
                case ".XLS":
                    return string.Format("Provider=Microsoft.ACE.OLEDB.12.0;;Data Source='{0}';Extended Properties='Excel 8.0;HDR=No;IMEX=1'", sourceFile);
                case ".XLSX":
                case ".XLSM":
                    return string.Format("Provider=Microsoft.ACE.OLEDB.12.0;;Data Source='{0}';Extended Properties='Excel 12.0;HDR=No;IMEX=1'", sourceFile);
                default:
                    throw new NotSupportedException("File type not supported.");
            }
        }
    
        private static string GetExcelColumnName(int columnNumber)
        {
            string columnName = String.Empty;
            int dividend = columnNumber;
            int modulo;
    
            while (dividend > 0)
            {
                modulo = (dividend - 1) % 26;
                columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
                dividend = (int)((dividend - modulo) / 26);
            }
    
            return columnName;
        }
    }
    }
    

    0 个答案:

    没有答案