快速从Excel中读取数据

时间:2016-09-09 15:13:38

标签: c# excel

我有以下代码从Excel工作表中读取数据并将其转换为管道分隔的文本文件。有用。问题是它很慢,因为我必须一次读取1个单元格才能添加管道。

我想知道是否有更好的方法可以做到这一点,即一步将数据读入内存/数组并在那里采取行动。

public string Process(string filename)
        {
            Excel.Application xlApp;
            Excel.Workbook xlWorkBook;
            Excel.Worksheet xlWorkSheet;
            Excel.Range range;
            string str = "";
            int rCnt = 0;
            int cCnt = 0;
            object misValue = System.Reflection.Missing.Value;

            xlApp = new Excel.Application();
            xlWorkBook = xlApp.Workbooks.Open(filename, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); //Use the 1st worksheet

            StreamWriter sw = new StreamWriter(destpath);
            range = xlWorkSheet.UsedRange;

            for (rCnt = 1; rCnt <= range.Rows.Count; rCnt++)
            {
                if ((rCnt % 1000) == 0)
                {
                    txtProgress.Text = "Rows processed: "+ rCnt;
                }
                for (cCnt = 1; cCnt <= range.Columns.Count; cCnt++)
                {
                    str = str + ToStr((range.Cells[rCnt, cCnt] as Excel.Range).Value2) + "|";
                }
                sw.WriteLine(str);
                str = "";

            }

            xlWorkBook.Close(true, null, null);
            xlApp.Quit();
            sw.Close();
            releaseObject(xlWorkSheet);
            releaseObject(xlWorkBook);
            releaseObject(xlApp);
            MessageBox.Show("Complete","Status");
            return "Success";
        }

 public static string ToStr(object readField)
        {
            if ((readField != null))
            {
                if (readField.GetType() != typeof(System.DBNull))
                {
                    return Convert.ToString(readField);
                }
                else
                {
                    return "";
                }
            }
            else
            {
                return "";
            }
        }

 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();
            }
        }

2 个答案:

答案 0 :(得分:1)

如果您打算只对excel文件内容执行读取,我建议您使用ExcelDataReader库Link,它将worksheetData提取到DataSet对象中。

    static void Main(string[] args)
    {
        IExcelDataReader reader = null;
        string FilePath = "PathToExcelFile";

        //Load file into a stream
        FileStream stream = File.Open(FilePath, FileMode.Open, FileAccess.Read);

        //Must check file extension to adjust the reader to the excel file type
        if (System.IO.Path.GetExtension(FilePath).Equals(".xls"))
        {
            reader = ExcelReaderFactory.CreateBinaryReader(stream);
        }
        else if (System.IO.Path.GetExtension(FilePath).Equals(".xlsx"))
        {
            reader = ExcelReaderFactory.CreateBinaryReader(stream);
        }

        if (reader != null)
        {
            //Fill DataSet
            System.Data.DataSet result = reader.AsDataSet();
            try
            {
                //Loop through rows for the desired worksheet
                //In this case I use the table index "0" to pick the first worksheet in the workbook
                foreach (DataRow row in result.Tables[0].Rows)
                {
                    string FirstColumn = row[0].ToString();
                }
            }
            catch
            {

            }
        }
    }

答案 1 :(得分:0)

您可以使用LinqToExcel nuget包

https://www.nuget.org/packages/LinqToExcel/1.10.1

示例代码:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[CSDN_CreateDemandeAppro]
    @EXER_FIN   nvarchar(8),
    @UNIT_ADM   nvarchar(6),
    @NOM_CONT   nvarchar(30),
    @MNT_TOTAL  numeric(15, 2)
AS
    DECLARE
            @NO_DA  nvarchar(8),
            @TYPE   nchar(1),
            @STAT   nchar(1),
            @ETAT   nchar(1),
            @IND_ENG    nchar(1),
            @IND_APPR   nchar(1),
            @TYPE_TRAIT nchar(1),
            @TEL    nvarchar(11),
            @POSTE  nvarchar(5),
            @NOM_ACHET  nvarchar(30),
            @COMMENT_ACHET  nvarchar(255),
            @DATE_CREAT smalldatetime,
            @DATE_MAJ   smalldatetime,
            @DATE_APPR  smalldatetime,
            @CODE_FOND  tinyint,
            @NO_COMM_DOFIN  nvarchar(9),
            @NO_MAG nvarchar(6),
            @NO_SEQ int,
            @NO_DA_OUT int

    BEGIN TRAN
        SELECT @NO_DA = PROC_NO_DA FROM ACH_UNIT_ADM_NUM WHERE UNIT_ADM = @UNIT_ADM and EXER_FIN = @EXER_FIN ;
        UPDATE ACH_UNIT_ADM_NUM SET PROC_NO_DA = @NO_DA + 1 WHERE UNIT_ADM = @UNIT_ADM and EXER_FIN = @EXER_FIN ;
    COMMIT;

    SET @TYPE = '0';
    SET @STAT = '3';
    SET @ETAT = 'C';
    SET @IND_ENG = '0';
    SET @IND_APPR = '0';
    SET @TYPE_TRAIT = '1';
    SET @TEL = NULL;
    SET @POSTE = NULL;
    SET @NOM_ACHET = NULL;
    SET @COMMENT_ACHET = 'APPROVISIONNEMENT.CSDN.QC.CA';
    SET @DATE_CREAT = GETDATE();
    SET @DATE_MAJ = GETDATE();
    SET @DATE_APPR = NULL;
    SET @CODE_FOND = '1';
    SET @NO_COMM_DOFIN = NULL;
    SET @NO_MAG = NULL;
    SET @NO_SEQ = 1;
    SET @NO_DA_OUT = 0;





    INSERT INTO DBO.ACH_DA 
    VALUES (
        @EXER_FIN,
        @NO_DA,
        @UNIT_ADM,
        @TYPE,
        @STAT,
        @ETAT,
        @IND_ENG,
        @IND_APPR,
        @TYPE_TRAIT,
        @NOM_CONT,
        @TEL,
        @POSTE,
        @NOM_ACHET,
        @COMMENT_ACHET,
        @DATE_CREAT,
        @DATE_MAJ,
        @DATE_APPR,
        @MNT_TOTAL,
        @NO_SEQ,
        @CODE_FOND,
        @NO_COMM_DOFIN,
        @NO_MAG);

    Select @NO_DA;