2017-05-22 6 views
1

차트가있는 Excel 파일이 있습니다.이 차트는 데이터를 열로 나타내며 열과 차트 변경으로이 데이터를 변경합니다.이 차트를 .png 파일로 내 보낸 다음, 프로그램이 동일한 파일의 두 인스턴스를 가지고있을 수 0x80030020 (STG_E_SHAREVIOLATION)엑셀 차트를 이미지로 내보내기

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

@NLindbom 맞습니다. 동일한 이름의 동일한 .png 파일을 루프에 만들고 저장하기 때문에 문제가 발생했습니다. 첫째, 모든 반복 작업 후에 파일을 삭제하려고했지만 "이 파일을 열었 기 때문에 삭제할 수 없습니다."와 같은 오류가 발생했습니다. 그래서, 나는 모든 차트에 대해 다른 .png 파일을 만들어서 문제를 해결했다. 그러나 그것을하는 것이 좋은 방법입니까 아니면 다른 것이 더 낫습니다. –

답변

0

:하지만 거기에 나는 예외 HRESULT를 만났다. 사진을 저장하기 전에 파일을 저장할 수도 있습니다.

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

그리고 위의 코드에 관한 발언 : (당신은 이미 당신은 항상 먼저 99 다음 완전히 무작위로 10 개 차트와 함께 종료됩니다 차트를 생성합니다 10 개 차트 11 시간을 생성하는 경우 있기 때문에, 결함의 첫째로 어떤 경우에는 처음부터 임의의 이름을 생성하고 싶을 수도 있습니다.) 대부분의 경우 모든 예외를 catch하고 true/false를 반환하는 것은 좋지 않습니다. 미래의 문제는 파일 이름과 관련이없는 다른 예외가 제기 될 때 발생할 수 있습니다. 사용자와 프로그래머 모두 어떤 일이 발생했는지 잊어 버릴 것입니다. 사용할 수있는 파일 이름을 요구하는 것이 좋습니다. 아마도 출력 파일 이름을 프로그램의 입력 매개 변수로 만들어 유연성을 제공하는 것이 좋습니다.

마지막 옵션은 비어 있음을 보장하고 거기에 선호하는 파일 이름을 출력하는 대신 새로운 임의의 출력 디렉토리를 만드는 것입니다. 또한 파일을 만들지 않는 Path.GetTempFileName() 이상의 이점을 가진 Path.GetRandomFileName()을 사용합니다.