2017-05-22 117 views
1

我有一个Excel文件,它有一个图表,这些图表表示的是列中的数据,在我的程序中,我还在列中更改了这些数据,并且还更改了图表更改,之后,我将这些图表导出为.png文件,但我遇到了一个异常HRESULT:0x80030020(STG_E_SHAREVIOLATION)将excel图表导出为图像

using System; 
using System.Collections.Generic; 
using System.Globalization; 
using System.IO; 
using System.Linq; 
using Excel = Microsoft.Office.Interop.Excel; 
using RTO.Models; 
using Novacode; 
using System.Drawing; 
using Word = Microsoft.Office.Interop.Word; 
using System.Reflection; 
using CommonLib.SharedModels; 

namespace RTO 
{ 
    class Program 
    { 
     public static void ReportRTO(RtoCommonData cmnData, List<Antenna> antennas) 
     { 
      Novacode.Image imageh, imagev, image1, image2; 
      Picture pictureh, picturev, picture1, picture2; 
      Paragraph pimg; 

      var exApp = new Excel.Application(); 
      exApp.ScreenUpdating = false; 
      var exBook = exApp.Workbooks.Open(fileLeaf); 
      var exSheet = exBook.Worksheets[1] as Excel.Worksheet; 
      Excel.Range r1 = exSheet.get_Range("A1", "A360"); 
      Excel.Range r2 = exSheet.get_Range("B1", "B360"); 
      double[,] d1 = new double[360, 1]; 
      double[,] d2 = new double[360, 1]; 
      int w = 1; 

      var application = new Excel.Application(); 
      application.ScreenUpdating = false; 
      var workbook = application.Workbooks.Open(fileExcel); 
      var worksheet = workbook.Worksheets[1] as Excel.Worksheet; 
      Excel.Range rng1 = worksheet.get_Range("A1", "A361"); 
      Excel.Range rng2 = worksheet.get_Range("B1", "B361"); 
      Excel.Range rng3 = worksheet.get_Range("C1", "C361"); 
      Excel.Range rng4 = worksheet.get_Range("D1", "D361"); 
      double[,] data1 = new double[361, 1]; 
      double[,] data2 = new double[361, 1]; 
      double[,] data3 = new double[361, 1]; 
      double[,] data4 = new double[361, 1]; 
      int flnmadd = 1; 

      for (int i = 0; i < antennas.Count; i++) 
      { 
       //Save chart as image 
       w = 1; 
       foreach (Excel.Worksheet ws in exBook.Worksheets) 
       { 
        Excel.ChartObjects chartObjects = (Excel.ChartObjects)(ws.ChartObjects(Type.Missing)); 
        foreach (Excel.ChartObject co in chartObjects) 
        { 
         co.Select(); 
         Excel.Chart chart = co.Chart; 
         chart.Export(exportPath + @"\leaf" + w + ".png", "PNG", false); 
         w++; 
        } 
       } 

       //Insert image to doc 
       image1 = doc.AddImage(leafimg1); 
       picture1 = image1.CreatePicture(); 
       picture1.Width = 310; 
       picture1.Height = 310; 
       image2 = doc.AddImage(leafimg2); 
       picture2 = image2.CreatePicture(); 
       picture2.Width = 310; 
       picture2.Height = 310; 
       pimg = doc.InsertParagraph(); 
       pimg.AppendPicture(picture1); 
       pimg.AppendPicture(picture2); 

       for (int j = 0; j < boztrows; j++) 
       { 
        data1[j, 0] = sumbozres[i].Rxhor[j]; 
        data2[j, 0] = sumbozres[i].Rzhor[j]; 
        data3[j, 0] = sumbozres[i].Rxver[j]; 
        data4[j, 0] = sumbozres[i].Rzver[j]; 
       } 
       data1[boztrows, 0] = data1[0, 0]; 
       data2[boztrows, 0] = data2[0, 0]; 
       data3[boztrows, 0] = data3[0, 0]; 
       data4[boztrows, 0] = data4[0, 0]; 
       rng1.Value = data1; 
       rng2.Value = data2; 
       rng3.Value = data3; 
       rng4.Value = data4; 

       //Save chart as image 
       flnmadd = 1; 
       foreach (Excel.Worksheet ws in workbook.Worksheets) 
       { 
        Excel.ChartObjects chartObjects = (Excel.ChartObjects)(ws.ChartObjects(Type.Missing)); 
        foreach (Excel.ChartObject co in chartObjects) 
        { 
         co.Select(); 
         Excel.Chart chart = co.Chart; 
         chart.Export(exportPath + @"\charthv" + flnmadd + ".png", "PNG", false); 
         flnmadd++; 
        } 
       } 

       //Insert image to doc 
       if (antennas[i].Type == "БС") 
       { 
        imageh = doc.AddImage(charthimg); 
        pictureh = imageh.CreatePicture(); 
        pictureh.Width = 624; 
        pictureh.Height = 357; 
        imagev = doc.AddImage(chartvimg); 
        picturev = imagev.CreatePicture(); 
        picturev.Width = 624; 
        picturev.Height = 156; 
        pimg = doc.InsertParagraph(); 
        pimg.AppendPicture(pictureh); 
        pimg = doc.InsertParagraph(); 
        pimg.AppendPicture(picturev); 
       } 
       else if (antennas[i].Type == "РРС") 
       { 
        imageh = doc.AddImage(rrsimg); 
        pictureh = imageh.CreatePicture(); 
        pictureh.Width = 624; 
        pictureh.Height = 156; 
        pimg = doc.InsertParagraph(); 
        pimg.AppendPicture(pictureh); 
       } 

       trsprev += trs; 
       freqs = ""; 
       pows = ""; 
       koefgs = ""; 
       koefgrazs = ""; 
       poteri = ""; 
       poteriraz = ""; 
       freqAvg = 0; 
      } 

      exBook.Save(); 
      exBook.Close(); 
      exApp.Workbooks.Close(); 
      exApp.Quit(); 
      workbook.Save(); 
      workbook.Close(); 
      application.Workbooks.Close(); 
      application.Quit(); 
     } 
    } 
} 
+0

此处显示异常:chart.Export(exportPath + @“\ leaf”+ w +“.png”,“PNG”,false); –

+0

STG_E_SHAREVIOLATION:“访问被拒绝,因为另一个调用者打开并锁定文件”。猜测是您被拒绝访问,因为具有相同文件名的旧文件已打开/正在使用中。在重新运行之前是否删除了旧文件? – NLindbom

+0

@Nindind你是对的,问题是因为我在循环中创建和保存相同的.png文件具有相同的名称。首先,我试图在每次迭代后删除文件,但出现“无法删除,因为此文件已打开”等错误。所以,我通过为每个图表创建不同的.png文件来解决问题。但是,这是一个好方法吗?还是有另一个更好? –

回答

0

可能是你的程序具有相同的文件的两个实例。在尝试保存图片之前,还可以保存文件。

0

正如在问题评论HRESULT指出:0x80030020(STG_E_SHAREVIOLATION)是“访问被拒绝,因为另一个调用者打开并锁定文件”更多信息here。该文件只是仍然打开/正在使用,可以通过首先删除旧文件来解决。

有一些选择,它取决于你打算如何使用该程序。添加一个try/catch语句可以防止程序崩溃。除此之外,我没有看到任何特别的最佳做法,这取决于使用情况。 在我看来,如果程序无法保存,程序退出是非常合理的。

在提供解决方案,你可以调整自己的喜好的兴趣:返回true,如果成功(不漂亮,但做这项工作)第一保存图表的方法:

using System.IO; 

private static bool SaveExcelChartAsPNG(ChartObject co, 
    string path, string filename) 
{ 
    try 
    { 
     string filenamePNG = Path.ChangeExtension(filename, "png"); 
     string fullFilenamePNG = Path.Combine(path, filenamePNG); 

     co.Select(); 
     co.Chart.Export(fullFilenamePNG, "PNG", false); 
    } 
    catch 
    { 
     // Save was not successful 
     return false; 
    } 
    return true; 
} 

该解决方案将在不成功的退出保存:

  foreach (var co in chartObjects) 
      { 
       if (!SaveExcelChartAsPNG(exportPath, @"\leaf" + w + ".png")) 
        Application.Exit(); 
      } 

较长的例子,将重试通过增加“W”参数保存10次,然后再尝试一个随机文件名。如果这不起作用,程序将退出。

  //Save chart as image 
      w = 1; 
      foreach (var ws in exBook.Worksheets) 
      { 
       var chartObjects = (Excel.ChartObjects)(ws.ChartObjects(Type.Missing)); 
       foreach (var co in chartObjects) 
       { 
        int retry = 0; 
        bool successfulSave = false; 
        while (!successfulSave && retry < 10) // retry by incerementing w parameter 10 times) 
        { 
         successfulSave = SaveExcelChartAsPNG(exportPath, @"\leaf" + w + ".png")) 
         retry++; 
         w++; 
        } 

        if (!successfulSave) 
        { 
         // Try again with random filename, otherwise exit 
         string filename = Path.GetRandomFileName(); 
         if (!SaveExcelChartAsPNG(exportPath, filename)) 
         { 
          // Save still not successful, exit 
          Application.Exit(); 
         } 
        } 
       } 
      } 

和关于上面的代码中的一句话:(首先是有缺陷的,因为如果你已经产生10个图表11倍,你总是会首先生成图表0-99,那么你将结束10张图使用完全随机的在这种情况下,您可能只想生成随机名称。) 在大多数情况下,捕获所有异常并返回true/false是不好的。当发生与文件名无关的其他异常时,可能会出现未来的问题。用户和程序员都会遗忘发生的事情。最好是要求可以使用的文件名,也许使'w'或输出文件名作为程序的输入参数来提供一些灵活性。

最后一个选项可能是创建一个新的随机输出目录,以保证它是空的并在那里输出优先文件名。也可以使用Path.GetRandomFileName(),其优点是不会创建文件,而不是Path.GetTempFileName()