繁体   English   中英

使用C#中的Excel Interop将更改提交到Excel文件

[英]Submitting changes to excel file using Excel Interop in C#

我仍然停留在此代码中,并且错误不断出现。.我有将近24列的excel文件,我正尝试将其改编为7列的excel文件,因为我拥有的软件只能在7列上工作,而我却没有想要从一开始就重新编写软件,因此您将看到一些列的删除和散列。

我在这个excel文件中有5列,这些列具有“ x”值或null。

我想做的是在范围A1和B1之间创建一个称为类别的新列,因此,如果第5列中有x,则在类别字段中写E,否则,如果x在第6列中然后我在类别列中写P。依此类推。 然后我需要删除不再需要的这5列(范围E1:I1)

问题是当我调试代码时,我可以看到values [,]插入了列,并且值已正确传输,但是当生成temp_data.csv时,删除后它具有新的excel文件,所以现在它包含11列,但是新的Category列及其值不存在...

                Microsoft.Office.Interop.Excel.Workbook workbook = xl.Workbooks.Open(p_sUBKPath, Type.Missing, false, 4, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Sheets[1];
                Microsoft.Office.Interop.Excel.Range range = ws.UsedRange;

                // delete columns that we don't need from the new excel file
                Microsoft.Office.Interop.Excel.Range range2 = ws.get_Range("A1","A1"); 
                range2.EntireColumn.Delete();
                Microsoft.Office.Interop.Excel.Range range3 = ws.get_Range("B1", "B1");
                range3.EntireColumn.Delete();
                Microsoft.Office.Interop.Excel.Range range4 = ws.get_Range("D1", "L1");
                range4.EntireColumn.Delete();
                Microsoft.Office.Interop.Excel.Range range5 = ws.get_Range("I1", "M1");
                range5.EntireColumn.Delete();
                Microsoft.Office.Interop.Excel.Range range6 = ws.get_Range("K1", "K1");
                range6.EntireColumn.Delete();

                //insert a new column ( Category)
                Microsoft.Office.Interop.Excel.Range range7 = ws.get_Range("B1", "B1");
                range7.EntireColumn.Insert(XlInsertShiftDirection.xlShiftToRight);


                object[,] tempVal = (object[,])range.Value2;
                tempVal[1, 2] = (object)"Category";

                for (int row = 2; row <= tempVal.GetUpperBound(0); row++)
                {

                    try
                    {

                        if ((!String.IsNullOrEmpty((string)tempVal[row, 5])) && (string)tempVal[row, 5] == "x")
                        {
                            tempVal[row, 2] = (string)"E";
                        }
                        else if ((!String.IsNullOrEmpty((string)tempVal[row, 6])) && (string)tempVal[row, 6] == "x")
                        {
                            tempVal[row, 2] = (string)"P";


                        }
                        else if ((!String.IsNullOrEmpty((string)tempVal[row, 7])) && (string)tempVal[row, 7] == "x")
                        {
                            tempVal[row, 2] = (string)"Phy";


                        }
                        else if ((!String.IsNullOrEmpty((string)tempVal[row, 8])) && (string)tempVal[row, 8] == "x")
                        {
                            tempVal[row, 2] = (string)"L";


                        }
                        else if ((!String.IsNullOrEmpty(tempVal[row, 9].ToString())) && (string)tempVal[row, 9] == "x")
                        {
                            tempVal[row, 2] = (string)"Ex";


                        }
                        else
                            MessageBox.Show("unknow");
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }


                }


                object[,] values = tempVal;
if (Convert.ToString(values[1, 1]).ToUpper().Trim() == "SHORT NAME" && Convert.ToString(values[1, 2]).ToUpper().Trim() == "CATEGORY" && Convert.ToString(values[1, 3]).ToUpper().Trim() == "LONG NAME EN" && Convert.ToString(values[1, 4]).ToUpper().Trim() == "LONG NAME DE" && Convert.ToString(values[1, 5]).ToUpper().Trim() == "ELEMENT" && Convert.ToString(values[1, 6]).ToUpper().Trim() == "PROPERNAME" && Convert.ToString(values[1, 7]).ToUpper().Trim() == "PHYSICAL" && Convert.ToString(values[1, 8]).ToUpper().Trim() == "LOGICAL" && Convert.ToString(values[1, 9]).ToUpper().Trim() == "EXTENSION" && Convert.ToString(values[1, 10]).ToUpper().Trim() == "CREATED BY" && Convert.ToString(values[1, 11]).ToUpper().Trim() == "CREATED ON" && Convert.ToString(values[1, 12]).ToUpper().Trim() == "STATE")

                {
                    for (int row = 1; row <= values.GetUpperBound(0); row++)
                        for (int col = 1; col <= values.GetUpperBound(1); col++)
                        {
                            string value = Convert.ToString(values[row, col]);

                            if (value.Contains(","))
                            {
                                range.Cells.set_Item(row, col, value.Replace(",", p_sPsuedostring));
                            }
                            if (value.Contains("    "))
                            {
                                range.Cells.set_Item(row, col, value.Replace("  ", p_sPsuedostring + "    " + p_sPsuedostring));
                            }
                        }
                    if (File.Exists(System.Windows.Forms.Application.StartupPath + @"\Data_Temp.csv")) 
                        File.Delete(System.Windows.Forms.Application.StartupPath + @"\Data_Temp.csv");

                   //Save the Latest databse as Data_Temp.csv
                    ws.SaveAs(System.Windows.Forms.Application.StartupPath + @"\Data_Temp.csv", Microsoft.Office.Interop.Excel.XlFileFormat.xlUnicodeText, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                    xl.DisplayAlerts = true;
                    try
                    {
                        xl.Workbooks[1].Close(false, Type.Missing, Type.Missing);
                    }
                    catch(Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                    xl.Application.Quit();
                    xl.Quit();
                    l_bClosedSuccessfully = true;

根据上述意见,假设您的Excel文件如下所示。 我已将需要删除的列涂成黄色。

屏幕截图

在此处输入图片说明

逻辑

  1. 以相反的顺序删除列,以使列的顺序不变,否则您将不得不考虑新移动的列
  2. 避免使用usedrange UsedRange还可以包含不必要的行/列,从而使您的代码变慢。 我正在找到包含数据的最后一个单元格,然后使用它的.Row.Column属性构造包含“ X”的范围
  3. 使用。 .Find和。 Findnext在您的范围内搜索“ X”。 找到后,获取找到的单元格的列号并从中减去2。 由于您只有5列,因此在从中减去2然后确定要使用的keyword之后,只需使用IF条件来检查Column的值是什么。

代码

尝试此代码(已尝试并已测试)

using System;
using System.Windows.Forms;
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;

Namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            Excel.Application xlexcel;
            Excel.Workbook xlWorkBook;
            Excel.Worksheet xlWorkSheet;
            Excel.Range Rng, aCell, bCell;
            String sMsg = "";

            object misValue = Missing.Value;
            xlexcel = new Excel.Application();
            xlexcel.Visible = true;

            //~~> Open a File (Chnage filename as applicable)
            xlWorkBook = xlexcel.Workbooks.Open("C:\\MyFile.xlsx",
                         0, true, 5, "", "", true,

            Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
            "\t", false, false, 0, true, 1, 0);

            //~~> Set Sheet 1 as the sheet you want to work with
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

            //~~> Delete relevant columns in reverse order
            //A,c,f,g,h,i,j,k,l,m,n,t,u,v,w,x,AA

            xlWorkSheet.get_Range("AA1", "AA1").EntireColumn.Delete();
            xlWorkSheet.get_Range("T1", "X1").EntireColumn.Delete();
            xlWorkSheet.get_Range("F1", "N1").EntireColumn.Delete();
            xlWorkSheet.get_Range("C1", "C1").EntireColumn.Delete();
            xlWorkSheet.get_Range("A1", "A1").EntireColumn.Delete();

            //~~> Insert the Category Column
            xlWorkSheet.get_Range("B1", "B1").EntireColumn.Insert(
            Excel.XlInsertShiftDirection.xlShiftToRight);

            //~~> get the last row and the last column of your data range
            //~~> This is much better than using usedrange  which might
            //'~~> include unnecessary ranges
            int lRow = xlWorkSheet.Cells.SpecialCells(
                       Excel.XlCellType.xlCellTypeLastCell, Type.Missing).Row;
            int lCol = xlWorkSheet.Cells.SpecialCells(
                       Excel.XlCellType.xlCellTypeLastCell, Type.Missing).Column;

            String Addr = xlWorkSheet.Cells[1, lCol].Address;
            //~~> This is to get the column name from column number
            String ColName = Addr.Split('$')[1];

            //~~> This is your data range. I am assuming that Row 1 has headers
            Rng = xlWorkSheet.get_Range("C2:" + ColName + lRow, misValue);

            //~~> Find the first occurance of "X"
            aCell = Rng.Find("X",misValue,Excel.XlFindLookIn.xlValues,
                    Excel.XlLookAt.xlWhole,misValue,
                    Excel.XlSearchDirection.xlNext,misValue,misValue,misValue);

            //~~> Find the next occurance of "X" using FindNext
            if(aCell != null)
            {
                //~~> Get the column number and subtract 2 from it
                int col = aCell.Column-2;

                //~~> Choose the relevant keyword
                if (col == 1)
                {
                    sMsg = "Element";
                }
                else if (col == 2)
                {
                    sMsg = "propername";
                }
                else if (col == 3)
                {
                    sMsg = "physical";
                }
                else if (col == 4)
                {
                    sMsg = "logical";
                }
                else if (col == 5)
                {
                    sMsg = "extension";
                }

                //~~> Populate the Category Column
                xlWorkSheet.Cells[aCell.Row, 2].Value = sMsg;

                string sFirstFoundAddress = aCell.get_Address(true, true,
                Excel.XlReferenceStyle.xlA1, misValue, misValue);

                bCell = Rng.Cells.FindNext(aCell);

                string sAddress = bCell.get_Address(true, true,
                Excel.XlReferenceStyle.xlA1, misValue, misValue);

                //~~> FindNext until the first found cell is found again
                While (!sAddress.Equals(sFirstFoundAddress))
                {
                    //~~> Get the column number and subtract 2 from it
                    col = bCell.Column-2;

                    //~~> Choose the relevant keyword
                    if (col == 1)
                    {
                        sMsg = "Element";
                    }
                    else if (col == 2)
                    {
                        sMsg = "propername";
                    }
                    else if (col == 3)
                    {
                        sMsg = "physical";
                    }
                    else if (col == 4)
                    {
                        sMsg = "logical";
                    }
                    else if (col == 5)
                    {
                        sMsg = "extension";
                    }

                    xlWorkSheet.Cells[bCell.Row, 2].Value = sMsg;

                    bCell = Rng.Cells.FindNext(bCell);

                    sAddress = bCell.get_Address(true, true,
                    Excel.XlReferenceStyle.xlA1, misValue, misValue);
                }
            }

            //~~> Once done close and quit Excel
            xlWorkBook.Close(true, misValue, misValue);
            xlexcel.Quit();

            //~~> CleanUp
            releaseObject(xlWorkSheet);
            releaseObject(xlWorkBook);
            releaseObject(xlexcel);
        }

        private void releaseObject(object obj)
        {
            try
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                obj = null;
            }
            catch (Exception ex)
            {
                obj = null;
                MessageBox.Show("Unable to release the Object " + ex.ToString());
            }
            finally
            {
                GC.Collect();
            }
        }
    }
}

屏幕截图 (运行代码后):

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM