异步读取Excel工作表

问题描述 投票:2回答:1

我试图异步读取给定工作簿的所有Excel工作表,但它在某种程度上没有发生。我们的想法是将每个Excel工作表中的前123个单元格相加并在最后打印它。代码编译并运行没有错误,但它没有读取所有工作表,它只是跳过那部分,因为async

namespace SyncAndAsync
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Excel = Microsoft.Office.Interop.Excel;

    class Startup
    {
        static void Main()
        {
            string filePath = @"C:\Users\Desktop\Sample.xlsx";
            Excel.Application excel = new Excel.Application();
            excel.Visible = true;
            excel.EnableAnimations = false;
            Excel.Workbook wkb = Open(excel, filePath);

            var calculation = CalculateAllWorksheetsAsync(wkb);

            //foreach (var item in calculation)
            //{
            //    Console.WriteLine(item);
            //}

            excel.EnableAnimations = true;
            wkb.Close(true);
            excel.Quit();
        }

        static async Task<List<Information>> CalculateAllWorksheetsAsync(Excel.Workbook wkb)
        {

            List<Task<Information>> tasks = new List<Task<Information>>();

            foreach (Excel.Worksheet wks in wkb.Worksheets)
            {
                Task.Run(() => CalculateSingleWorksheetAsync(wks));
            }

            var results = await Task.WhenAll(tasks);
            return new List<Information>(results);
        }

        static async Task<Information> CalculateSingleWorksheetAsync(Excel.Worksheet wks)
        {
            Information output = new Information();
            int result = 0;
            await Task.Run(() =>
            {
                for (int i = 1; i <= 123; i++)
                {
                    result += (int)(wks.Cells[i, 1].Value);
                }
            });

            output.WorksheetName = wks.Name;
            output.WorksheetSum = result;
            Console.WriteLine($"{wks.Name} - {result}");
            return output;
        }

        static Excel.Workbook Open(Excel.Application excelInstance,
                                            string fileName, bool readOnly = false,
                                            bool editable = true, bool updateLinks = true)
        {
            Excel.Workbook book = excelInstance.Workbooks.Open(
                fileName, updateLinks, readOnly,
                Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                Type.Missing, editable, Type.Missing, Type.Missing, Type.Missing,
                Type.Missing, Type.Missing);
            return book;
        }
    }
}

添加Information类以使用任务,可能会跳过它:

namespace SyncAndAsync
{
    class Information
    {
        public string WorksheetName { get; set; } = "";
        public int WorksheetSum { get; set; } = 0;
    }
}

依赖关系:

  • 应添加参考Microsoft.Office.Interop.Excel;
  • string filePath = @"C:\Users\Desktop\Sample.xlsx";更改为相关的内容,并确保在Excel文件中每张工作表的第一列中都有一些数字,以获得结果;

问题 - 如何进行异步运行并显示所有工作表的总和?

c# excel office-interop com-interop excel-interop
1个回答
1
投票

有几个问题。首先,任务列表永远不会被填充,因此WhenAll调用不会执行任何操作。其次,主要功能永远不会等待CalculateAllWorksheetsAsync的结果。我对您的代码进行了一些修改,请参阅下文:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;

namespace ExcelTest {
    public class Information {
        public Information(string name, int sum) {
            Name = name;
            Sum = sum;
        }

        public string Name { get; set; }
        public int Sum { get; set; }
    }

    class Program {
        static void Main(){
            MainAsync().GetAwaiter().GetResult();
        }

        private static async Task MainAsync() {
            const string filePath = @"D:\file.xlsx";
            var excel = new Excel.Application {Visible = true, EnableAnimations = false};
            var wkb = Open(excel, filePath);

            var calculation = await CalculateAllWorksheetsAsync(wkb);

            foreach (var item in calculation) {
                Console.WriteLine($"{item.Name} - {item.Sum}");
            }

            excel.EnableAnimations = true;
            wkb.Close(true);
            excel.Quit();
            Console.Read();
        }

        private static async Task<List<Information>> CalculateAllWorksheetsAsync(Excel.Workbook wkb) {
            var tasks = wkb.Worksheets.Cast<Excel.Worksheet>().Select(CalculateSingleWorksheetAsync);
            var results = await Task.WhenAll(tasks);
            return results.ToList();
        }

        private static async Task<Information> CalculateSingleWorksheetAsync(Excel.Worksheet wks) {
            int result = await Task.Run(() =>
                Enumerable.Range(1, 123).Sum(index => (int) (wks.Cells[index, 1].Value2)));

            Console.WriteLine($"{wks.Name} - {result}");
            return new Information(wks.Name, result);
        }

        private static Excel.Workbook Open(Excel.Application excelInstance,
            string fileName, bool readOnly = false,
            bool editable = true, bool updateLinks = true) {
            return excelInstance.Workbooks.Open(
                fileName, updateLinks, readOnly,
                Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                Type.Missing, editable, Type.Missing, Type.Missing, Type.Missing,
                Type.Missing, Type.Missing);
        }
    }
}

样本输出:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.