如何在 C# 的线程中以编程方式复制 Excel 文件时修复访问拒绝错误

Posted

技术标签:

【中文标题】如何在 C# 的线程中以编程方式复制 Excel 文件时修复访问拒绝错误【英文标题】:How to fix access denial error when copying an excel file programmatically within a thread in C# 【发布时间】:2019-12-15 18:15:07 【问题描述】:

我正在编写一个程序,它将一个 excel 文件复制到另一个位置并删除除可见工作表之外的工作表并保存复制的文件。为了实现这一点,我使用了 BackgroundWorker 类。

首先,我初始化了 Background Worker 方法。

private void InitializeBackgroundWorker()
        
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.WorkerSupportsCancellation = true;
            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
        

“BackgroundWorker.DoWork()”方法如下。

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        
            BackgroundWorker worker = sender as BackgroundWorker;

            GenerateReports(worker);

            // Cancel the asynchronous operation.
            if (worker.CancellationPending)
            
                e.Cancel = true;
                return;
            

            worker.ReportProgress(100);

            if(backgroundWorker.IsBusy)
            
                this.backgroundWorker.CancelAsync();
            
        

“GenerateReports()”方法包含“ExtractVisibleSheets()”方法,该方法提取可见工作表,然后调用“CopyVisibleSheets()”方法。

private void ExtractVisibleSheets(String originalDirectory, String convertedDirectory)
        
           //Get the .xlsx files of the original reports and the converted reports
            visibleSheetsOriginal = Directory.GetFiles(originalDirectory, "*.xlsx");
            visibleSheetsConverted = Directory.GetFiles(convertedDirectory, "*.xlsx");

            //Copy the visible sheets to the defined workbooks
            //Sample Reports
            CopyVisibleSheets(originalDirectory, visibleSheetsOriginal, visibleSheetsBasePath);

            //Converted Reports
            CopyVisibleSheets(convertedDirectory, visibleSheetsOriginal, visibleSheetsConvertedPath);                
        
private void CopyVisibleSheets(String directory, String[] excelFiles, String path)
        
            excelApplication = null;
            workbook = null;
            Excel.Worksheet sheet = null;
            String copiedReport = "";

            try
            
                foreach(String report in excelFiles)
                
                    copiedReport = path + "\\" + report.Substring(report.LastIndexOf('\\') + 1);

                    excelApplication = GetExcelApplication();

                    File.Copy(report, copiedReport);

                    OpenXmlFileProcessor.RemoveCustomProperty(copiedReport, FileProcessor.BaClientVerParam);

                    workbook = excelApplication.Workbooks.Open(copiedReport);

                    EnableDisableAlertsAndEvents(false);

                    for (int i = workbook.Worksheets.Count; i > 0; i--)
                                           
                        sheet = excelApplication.ActiveWorkbook.Worksheets[i];
                        if(sheet.Visible != XlSheetVisibility.xlSheetVisible)
                        
                            sheet.Visible = XlSheetVisibility.xlSheetVisible;
                            sheet.Delete();                            
                                                                     
                    

                    workbook.Save();

                    EnableDisableAlertsAndEvents(true);

                    workbook.Close();

                    Marshal.ReleaseComObject(workbook);
                                
            
            finally
            
                QuitAndReleaseExcelApplication(false);
            
        

下面给出“BackgroundWorker.RunWorkerCompleted()”方法

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        
            // First, handle the case where an exception was thrown.
            if (e.Error != null)
            
                MessageBox.Show(e.Error.Message);
            
            else if (e.Cancelled)
            
                // Next, handle the case where the user cancelled 
                // the operation.
            
            else
            
                // Finally, handle the case where the operation 
                // succeeded.                
                MessageBox.Show("Directory Generation Successful!");                    
            

            EnableControls();
        

但是在“File.Copy(report,copyedReport)”行中发生如下错误,并从“BackgroundWorker.RunWorkerCompleted()”方法中触发。

Error

如果有人知道此错误的原因,请告诉我。

【问题讨论】:

我会试一试,说这是因为文件路径被拒绝访问... 我怀疑你忘了使用你传入的 directory 变量。 传递给File.Copy(report, copiedReport)方法的实际值是多少? @mjwills 在我添加线程部分之前它工作正常,我将尝试添加一个简短的示例。 @EugeneAstafiev 报告的值为“Sample_1.xlsx”,copyReport 的值为与报告名称组合的路径。即“C:\\SampleFolder\\Sample_1_Copy” 【参考方案1】:

通常,系统C: 驱动器需要管理员权限才能写入。我建议选择另一个驱动器或文件夹(应用程序数据)。

【讨论】:

【参考方案2】:
path + "\\" + report.Substring(report.LastIndexOf('\\') + 1);
try to use double qute "" (report.LastIndexOf('\\') + 1); 

its a type of strings 
try to use path + "//" + report.Substring(report.LastIndexOf("//") + 1);

如果我错了,请纠正我:)

【讨论】:

嗨,这与路径的格式无关,因为它在我添加线程部分之前就起作用了:)

以上是关于如何在 C# 的线程中以编程方式复制 Excel 文件时修复访问拒绝错误的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中以编程方式从 Excel 文件中大量导入数据到 Access

在JAVA中以编程方式监视JVM的堆栈区域? [复制]

如何在 C# 中以编程方式获取 Lync 会议 URL?

如何在 C# 中以编程方式安装 Windows 服务?

C# winform中以excel的方式编辑表格

如何在 C# 中以编程方式将 Windows 服务的启动类型更改为禁用