我有一个Excel文件,其中有一个图表,这些图表代表列中的数据,在我的程序中我更改这些数据的列和图表更改,之后我将这些图表导出到.png文件中,但我遇到了一个异常HRESULT: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 :(得分:0)
可能是您的程序有两个同一文件的实例。另一件事可以是在您尝试保存图片之前保存文件。
答案 1 :(得分: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()
无法创建文件。