C#删除unicode字符

时间:2015-10-27 13:21:19

标签: c# excel unicode sqlbulkcopy

我尝试使用C#sqlBulkCopy类将Excel工作表中的文本数据插入到MS SQL表中。我遇到的问题是我得到臭名昭着的从bcp客户端收到无效的列长度,因为colid 6 错误。我后来发现真正的问题是注释文本中的Excel Unicode格式。如果我只是在Excel单元格中输入注释,数据插入就会起作用,否则会失败。以下是我在C#脚本中尝试使用的代码:

 SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(DBconn.ConnectionString);
            {
                sqlBulkCopy.DestinationTableName = "##MasterFileTemp";



                foreach (DataColumn dc in MasterFileTemp.Columns)
                {
                    for (int j = 1; j < MasterFileTemp.Rows.Count - 1; j++)
                    {
                        if (MasterFileTemp.Rows[0][dc].ToString() == "Notes")
                        {

                            int pos = dc.Ordinal;
                            string dataText = Regex.Replace(MasterFileTemp.Rows[j][pos].ToString(), @"[^\u0000-\u007F]", string.Empty);
                            MasterFileTemp.Rows[j][pos] = dataText;
                            MasterFileTemp.AcceptChanges();
                            MessageBox.Show(MasterFileTemp.Rows[j][pos].ToString());


                        }
                    }
                }
                sqlBulkCopy.WriteToServer(MasterFileTemp);

这是Excel文本数据的样子,注意Excel生成的前导和尾随双引号:

&#34; - 如果需要其他信息,请在工作区内的“服务订单”选项卡上联系合作伙伴请求者。对于任何其他运营问题,请发送电子邮件给James

**服务请求包括投资组合管理(监管清单),丧失抵押品赎回权,止赎前,其他房地产(OREO),仅限资产评估(无贷款)

&#34;

string strCn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1;\";";
string GetExcelData = "Select * From [" + tabName + "A23:Z100]";
OleDbConnection cn = new OleDbConnection(strCn);
OleDbDataAdapter objAdapter2 = new OleDbDataAdapter(GetExcelData, cn);
                    DataSet ds2 = new DataSet();
                    objAdapter2.Fill(ds2, "dSheet1");
                    DataTable dt2 = ds2.Tables["dSheet1"];


      Here the entired code: 

命名空间ST_426cda87cffe4ef6a10722ecf5f7fe65.csproj {     [System.AddIn.AddIn(&#34; ScriptMain&#34;,Version =&#34; 1.0&#34;,Publisher =&#34;&#34;,Description =&#34;&#34;) ]     public partial class ScriptMain:Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase     {

    #region VSTA generated code
    enum ScriptResults
    {
        Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
        Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
    };
    #endregion

    public void Main()
    {

        Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
        Microsoft.Office.Interop.Excel.Workbook excelBook = xlApp.Workbooks.Open(Dts.Variables["User::MasterFileTemplate"].Value.ToString(),
             0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);

        String[] excelSheets = new String[excelBook.Worksheets.Count];
        int z = 0;
        foreach (Microsoft.Office.Interop.Excel.Worksheet wSheet in excelBook.Worksheets)
        {
            excelSheets[z] = wSheet.Name;
            z++;
        }
        excelBook.Close(false, Dts.Variables["User::MasterFileTemplate"].Value.ToString(), Missing.Value);
        xlApp.Quit();
        process_worksheets(excelSheets);
    }

    public void process_worksheets(string[] wsheets)
       {
        int r;            
        string[] vars = new string[1];
        string field;
        string filePath = (Dts.Variables["User::MasterFileTemplate"].Value.ToString());
        string DataServer = (Dts.Variables["User::DataServer"].Value.ToString());
        string strCn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1;\";";


          for (r=0; r < wsheets.Length; r++)
               {
                string tabName = wsheets[r].ToString() + "$";
                string GetExcelDate = "Select * From [" + tabName + "A15:B16]";   //This is the Excel line number for Prod Completed date and Completed by
                string GetExcelData = "Select * From [" + tabName + "A23:Z100]";  //This is the Excel line number where the header columns and data start   

                OleDbConnection cn = new OleDbConnection(strCn);
                SqlConnection DBconn = new SqlConnection();
                DBconn.ConnectionString = "Data Source="+DataServer + ";Initial Catalog=FNC;" + "Integrated Security=SSPI";

                OleDbDataAdapter objAdapter = new OleDbDataAdapter(GetExcelDate, cn);

                // This Dataset contains the header columns and data
                DataSet ds = new DataSet();
                objAdapter.Fill(ds, "dSheet1");
                DataTable dt = ds.Tables["dSheet1"];

                ///****  Parse Excel Serial Date  ***/
                string dtt = (dt.Rows[0][1].ToString());
                DateTime signoffDte = DateTime.Parse(dtt);
                DateTime currentDte = System.DateTime.Today;

                /// Check to see if Production sign-off date is less than current date and signed by is empty
                if ((signoffDte > currentDte) || (dt.Rows[1][1].ToString() == ""))
                {
                 //   MessageBox.Show(tabName.ToString() + "Date requirment Failed..processing next");
                    continue;  //Skip worksheet if Production signoff date or signature is invalid
                }
                else
                {
                    //This Dataset contains the header columns and data
                    OleDbDataAdapter objAdapter2 = new OleDbDataAdapter(GetExcelData, cn);
                    DataSet ds2 = new DataSet();
                    objAdapter2.Fill(ds2, "dSheet1");
                    DataTable dt2 = ds2.Tables["dSheet1"];


                    DataTable dth = dt2.Clone();
                    dth.ImportRow(dt2.Rows[0]);

                    /*** Create Master File Temp Table from Excel Template source file ***/
                    CreateTempTableAndBulkCopyData(dt2,DBconn);

                    /*****************************************************************************/
                    /*   Loop thru Excel Template File and only select the first row (Headers)   */
                    /*****************************************************************************/

                    for (int i = 0; i < 1; i++)  //Gets first row "A1:Z1" (column headers of excel spreadsheet)
                    {
                        // y=3 is static and must not be changed. This sets Partner_org_PK,Partner_ID,Partner_Name as key columns to perform SQL JOIN on
                        for (int y = 3; y < dth.Columns.Count; y++)
                        {
                            field = dth.Rows[0][y].ToString();
                            vars[0] = field;
                           UpdateMasterFileTable(DBconn, vars, dth); // Performs an update to the Partner Profile Table via a join on the Master File Temp table 

                        }
                        UpdateValidation(DBconn, dth, tabName);
                    }
                    ds.Clear();
                    ds2.Clear();
                    dt.Clear();
                    dth.Clear();

                    cn.Close();
                    DBconn.Close();
                    Dts.TaskResult = (int)ScriptResults.Success;
                }
                MessageBox.Show("Processed......" + tabName.ToString());
                System.Threading.Thread.Sleep(3000);
            }
 }
     /**************************************************************************************************/
     /*   Creates Master File Global Temp Table ###MasterFileTemp and Bulk Copy Excel data into it   */
     /**************************************************************************************************/
    public static void CreateTempTableAndBulkCopyData(DataTable dt2, SqlConnection DBconn)
    {
        DataTable MasterFileTemp = dt2;



        string createTempTable = "CREATE TABLE ##MasterFileTemp(";
        foreach (DataColumn dc in MasterFileTemp.Columns)
        {
            createTempTable += MasterFileTemp.Rows[0][dc] + " Varchar(255),";
        }
        createTempTable = createTempTable.Remove(createTempTable.Length - 1);   //remove trailing, unecessary comma
        createTempTable += ")"; // cap-off with ")" to complete the CREATE ##TEMP TABLE DDL
        {

            //Create temp table command
            SqlCommand command = new SqlCommand(createTempTable, DBconn);
            DBconn.Open();
            command.ExecuteNonQuery();
            MessageBox.Show(createTempTable.ToString());

            //Copy the DataTable to SQL Server Table using SqlBulkCopy
            SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(DBconn.ConnectionString);
            {
                sqlBulkCopy.DestinationTableName = "##MasterFileTemp";

                foreach (DataColumn dc in MasterFileTemp.Columns)
                {
                    for (int j = 1; j < MasterFileTemp.Rows.Count - 1; j++)
                    {
                        if (MasterFileTemp.Rows[0][dc].ToString() == "Notes")
                        {

                            int pos = dc.Ordinal;
                            string dataText = MasterFileTemp.Rows[j][pos].ToString().Replace("\r\n", String.Empty);
                            MasterFileTemp.Rows[j][pos] = dataText;
                            MasterFileTemp.AcceptChanges();
                            //MessageBox.Show(MasterFileTemp.Rows[j][pos].ToString());

                        }
                    }
                }
                sqlBulkCopy.WriteToServer(MasterFileTemp);

            }
        }
    }
    /**************************************************************************************************/
    /*   Performs an up to the Partner Profile Table via a UPDATE join on the Master File Temp table  */
    /**************************************************************************************************/
    public void UpdateMasterFileTable(SqlConnection DBconn, string[] vars, DataTable dth)
        {
         string[] upvariable = vars;
         string sqlUpate = "UPDATE [dbo].[xstg_Partner_Profile]" +
         " SET [dbo].[xstg_Partner_Profile]." + upvariable[0] + "=##MasterFileTemp." + upvariable[0] +
         " FROM ##MasterFileTemp" +
         " WHERE [dbo].[xstg_Partner_Profile].Partner_Id= ##MasterFileTemp." + dth.Rows[0][1].ToString() +
         " AND [dbo].[xstg_Partner_Profile].Partner_Name= ##MasterFileTemp." + dth.Rows[0][2].ToString();
          SqlCommand command = new SqlCommand(sqlUpate, DBconn);
           command.ExecuteNonQuery();
          MessageBox.Show(sqlUpate.ToString());

         }
    /**************************************************************************************************/
    /*   Performs the update validation against production 90100 UI Report and creates Excel mismatch */
    /*   output for each worksheet tab in masterfileupdate template
    /**************************************************************************************************/
    public void UpdateValidation(SqlConnection DBconn, DataTable dth, string tabName)
    {
        string SelectSQL;
        string SelectFields=null;
        for (int x = 3; x < dth.Columns.Count; x++)
        {
           SelectFields += " p2." +dth.Rows[0][x]+ ", ";
        }
        SelectFields = SelectFields.Remove(SelectFields.Length - 2);  //remove trailing comma
        SelectSQL = "SELECT p2.Partner_ID, p2.Partner_Name,";
        SelectSQL += SelectFields;
        string ValidationSQL = " FROM (select * from dbo.Partner_Profile_CMS_Settings) p1" +
                               " FULL OUTER JOIN (Select * from dbo.xstg_Partner_Profile) p2" +
                               " ON p1.Partner_ID = p2.Partner_ID and p1.Partner_Name=p2.Partner_Name" +
                               " WHERE";

        SelectSQL += ValidationSQL; //Append select statement as one
        string ValidationSQLWhere=null;
        for (int y = 3; y < dth.Columns.Count; y++) //loop through data columns to get columns for update - mismatch. This is dynamic and makes up the Where clause
        {
            ValidationSQLWhere += " (P1."+dth.Rows[0][y]+" <> p2."+dth.Rows[0][y]+") OR";
        }
        ValidationSQLWhere = ValidationSQLWhere.Remove(ValidationSQLWhere.Length - 2);  //Remove "OR" two characters from the select statement where clause
        SelectSQL += ValidationSQLWhere; //Append Where clause string to main Select string
        MessageBox.Show("Validating... " + tabName); //Display entire string

        //Build SQL connection to run mismatch query, passing in SELECT statement above
        SqlDataAdapter VSAdapter = new SqlDataAdapter(SelectSQL, DBconn);
        // This Dataset contains Vaildate data
        DataSet validateDs = new DataSet();
        VSAdapter.Fill(validateDs, "VSheet1");
        DataTable validationTemp = validateDs.Tables["VSheet1"];
        String currentDate = DateTime.Now.ToString("MMddyyyy");
        String outputStatus="Validation is 100% accurate";


        /* Set up Excel workbook instance and loop through each worksheet avaialble file output */
        /****************************************************************************************/
        Excel.Application oXL = new Excel.ApplicationClass();
        oXL.DisplayAlerts = false;
        Excel.Workbooks oWBs = oXL.Workbooks;
        Excel.Workbook oWB = null;
        Excel.Worksheet oSheet;
        tabName = tabName.Remove(tabName.Length-1);  //remove training '$' from mismatch worksheets

        /* If the mismatch output file does not exist, create mismatch file and write out first worksheet */
        if (!File.Exists(Dts.Variables["User::MismatchOutputFile"].Value.ToString()))
        {


            oWB = oXL.Workbooks.Add(Missing.Value);
            // Get the active sheet 
            oSheet = (Excel.Worksheet)oWB.Worksheets.get_Item(1);
            oSheet.Name = tabName;

            int rowCount = 0;
            if (validationTemp.Rows.Count >= 1)
            {
                foreach (DataRow dr in validationTemp.Rows)
                {
                    rowCount += 1;
                    for (int i = 1; i < validationTemp.Columns.Count + 1; i++)
                    {
                        // Add the header time first only
                        if (rowCount == 2)
                        {
                            oSheet.Cells[1, i] = validationTemp.Columns[i - 1].ColumnName;
                        }                           
                        oSheet.Cells[rowCount, i] = dr[i - 1].ToString();
                    }
                }
            }
            else
            {
               // MessageBox.Show("Validation is 100% accurate");
                oSheet.Cells[rowCount, 2] = outputStatus.ToString();
            }
            oWB.SaveAs(Dts.Variables["User::MismatchOutputFile"].Value.ToString(), Excel.XlFileFormat.xlWorkbookNormal,
               Missing.Value, Missing.Value, Missing.Value, Missing.Value,
               Excel.XlSaveAsAccessMode.xlShared,
               Missing.Value, Missing.Value, Missing.Value,
               Missing.Value, Missing.Value);
         }
        else /* If mismatch file already exists, loop thru and append additional worksheets */
        {
           System.Threading.Thread.Sleep(1000);
            try
            {
                oXL.DisplayAlerts = false;
                Excel.Sheets xlSheets = null;
                oWB = oXL.Workbooks.Open(Dts.Variables["User::MismatchOutputFile"].Value.ToString(),
                         Missing.Value, Missing.Value, Missing.Value, Missing.Value,
                         Missing.Value, Missing.Value, Missing.Value, Missing.Value,
                         Missing.Value, Missing.Value, Missing.Value,
                         Missing.Value, Missing.Value, Missing.Value);
                xlSheets = (Excel.Sheets)oWB.Sheets;
                oSheet = (Excel.Worksheet)xlSheets.Add(Type.Missing, xlSheets[1], Type.Missing, Type.Missing);
                oSheet.Name = tabName;
                int rowCount = 0;
                if (validationTemp.Rows.Count > 1)
                {
                    foreach (DataRow dr in validationTemp.Rows)
                    {
                        rowCount += 1;
                        for (int i = 1; i < validationTemp.Columns.Count + 1; i++)
                        {
                            // Add the header time first only
                            if (rowCount == 2)
                            {
                                oSheet.Cells[1, i] = validationTemp.Columns[i - 1].ColumnName;
                            }
                            oSheet.Cells[rowCount, i] = dr[i - 1].ToString();
                        }
                    }
                 }else
                        {
                           // MessageBox.Show("Validation is 100% accurate");
                            oSheet.Cells[rowCount, 2] = outputStatus.ToString();
                        }   
                oWB.SaveAs(Dts.Variables["User::MismatchOutputFile"].Value.ToString(), Excel.XlFileFormat.xlWorkbookNormal,
                   Missing.Value, Missing.Value, Missing.Value, Missing.Value,
                   Excel.XlSaveAsAccessMode.xlExclusive,
                   Missing.Value, Missing.Value, Missing.Value,
                   Missing.Value, Missing.Value);
                oWB.Close(true, Dts.Variables["User::MismatchOutputFile"].Value.ToString(), Type.Missing);
                oWBs.Close();
                oXL.Quit();
                Marshal.ReleaseComObject(oXL);
            }
            finally
            {

            }
        }

    }

}

}

2 个答案:

答案 0 :(得分:0)

您说的是Excel,但您的代码使用的是DataTable。为什么不直接从Excel本身直接使用SqlBulkCopy?

您可以将SqlBulkCopy转换为本地临时表,而不是使用全局临时表,而是设置文本字段&#39;数据类型为NVarchar(max),你不应该有问题。 SQL Server支持unicode。

编辑:啊哈,我想现在我知道你哪里出错了。 &#34; Excel生成的文本数据&#34;你说。那是一个CSV文件吗? Excel并不知道如何首先保存合法的CSV。不要保存到文本文件中。如果你这样做,那么就没有“进口商”这样做了。那可以正确地读取数据。而是直接使用Excel中的SqlBulkCopy而不使用任何其他中间文本文件或数据表。

答案 1 :(得分:0)

问题已解决。我发现列大小太小,无法容纳sqlBlkCopy操作。将大小从varchar(255)更改为varchar(2000)