2017-05-22 58 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()