|
ありがとうございます.
プログラムから一部をコピーした際に, "}"が抜けておりました. 申し訳ございません.
ReleaseComObjectについては理解ができていませんでした. また,C#での遅延処理は,Sleepなどでしょうか.
以下のようにプログラムを変更して, エラーが出るCopyPictureの周りでSleepを入れたのですが, 状況の改善は見られませんでした.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing.Imaging; using Microsoft.Office.Interop.Excel; using System.IO; using System.Threading; using System.Runtime.InteropServices;
namespace Excel2Image {
public partial class Form1 : Form {
string excelPath;
int _sheetNum = 6;
int _A1 = 9; int _A2 = 4; int _A3 = 23; int _A4 = 29;
//int _photoNum; int _P1 = 9; int _P2 = 8;
int i = 1; int pageNum = 1;
bool flg1 = false; bool flg2 = false;
public Form1() { InitializeComponent(); }
private void button1_Click(object sender, EventArgs e) { OpenFileDialog openFile = new OpenFileDialog();
openFile.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
openFile.Filter = "Excelファイル(*.xls;*.xlsx)|*.xls;*.xlsx"; openFile.FilterIndex = 1; DialogResult result = openFile.ShowDialog();
if (result == DialogResult.OK) { excelPath = openFile.FileName;
Microsoft.Office.Interop.Excel.Application ExcelApp = new Microsoft.Office.Interop.Excel.Application(); ExcelApp.Visible = false;
Microsoft.Office.Interop.Excel.Workbook ExcelWorkbook = ExcelApp.Workbooks.Open(excelPath);
Worksheet sheet = ExcelWorkbook.Sheets[_sheetNum]; sheet.Select();
while (sheet.Cells[_P1, _P2].Text != "") {
Range range = sheet.Range[sheet.Cells[_A1, _A2], sheet.Cells[_A3, _A4]];
Thread.Sleep(1000); range.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap); Thread.Sleep(1000);
IDataObject data = Clipboard.GetDataObject();
if (data.GetDataPresent(DataFormats.Bitmap)) {
Bitmap bmp = (Bitmap)data.GetData(DataFormats.Bitmap);
bmp.Save(i.ToString() + ".jpg", ImageFormat.Jpeg);
i++;
}
if ((flg1 == false) && (flg2 == false)) { flg1 = true; _A1 = 9 + 38 * (pageNum - 1); _A2 = 30; _A3 = 23 + 38 * (pageNum - 1); _A4 = 55;
} else if ((flg1 == true) && (flg2 == false)) { flg2 = true; _A1 = 24 + 38 * (pageNum - 1); _A2 = 4; _A3 = 38 + 38 * (pageNum - 1); _A4 = 29;
} else if ((flg1 == true) && (flg2 == true)) { flg1 = false; _A1 = 24 + 38 * (pageNum - 1); _A2 = 30; _A3 = 38 + 38 * (pageNum - 1); _A4 = 55;
} else if ((flg1 == false) && (flg2 == true)) { pageNum++; flg2 = false;
_A1 = 9 + 38 * (pageNum - 1); _A2 = 4; _A3 = 23 + 38 * (pageNum - 1); _A4 = 29;
}
_P1 = _A1; _P2 = _A2 + 4;
Marshal.ReleaseComObject(sheet.Cells[_P1, _P2]); Marshal.ReleaseComObject(sheet.Cells[_A1, _A2]); Marshal.ReleaseComObject(sheet.Cells[_A3, _A4]);
}
Marshal.ReleaseComObject(sheet); sheet = null; Marshal.ReleaseComObject(ExcelWorkbook); ExcelWorkbook = null; ExcelApp.Quit(); Marshal.ReleaseComObject(ExcelApp); ExcelApp = null; GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } } } }
■No102828 (魔界の仮面弁士 さん) に返信 > ■No102826 (Massa さん) に返信 >>Excelのセル範囲を一定間隔でずらしながら,画像として出力するプログラムをC#で作成しています. > ReleaseComObject 関連の解放処理がゴッソリ抜け落ちてますね…。 > > C# からアウトプロセスで呼び出しているものなので、解放漏れがあると > Quit() 後も Excel のインスタンスが非表示で残り続ける要因に繋がりますよ。 > > >>range.CopPictureのところでエラーになるときとならないときがあり,不安定なってしまいます. > スペルミスに目をつぶるとしても、提示されたコードは > 「{」が 11 個、 > 「}」が 9 個 > という非対称なものであり、そもそもコンパイルが通りそうにありません…。 > > >>エラーメッセージは「range クラスの copypicture メソッドが失敗しました。」と表示されます. > クリップボードが使用中などで処理できなかった場合に、そのようなエラーが発生することがあります。 > 事象としては、Excel VBA だけで実施した場合にも起きえます。 > > 他のアプリがクリップボード操作している場合や、PC のパフォーマンスが落ちている場合、 > あるいは、クリップボードを連続して操作した場合などに起きやすいという説もありますが、 > 根本的な対策は無いので、遅延処理やリトライなどを独自に組み込んで対処している方が多いようです。 > > https://answers.microsoft.com/ja-jp/msoffice/forum/all/%E5%AE%9F%E8%A1%8C%E6%99%82%E3%82%A8%E3%83%A9/63090c23-3e6c-4855-80c5-d9e8684972c8 > https://social.msdn.microsoft.com/Forums/ja-JP/35487cfb-26a1-465a-bc5e-a331d98f7a4e/123041237225945310341236712384123731235612305excel2016?forum=vbajp > https://vba-create.jp/vba-method-copypicture/ > > >>解決法についてご教示いただければ幸いです. > 失敗した場合は、いったん現状の Click イベントを return で一時的に抜けて、 > 残りの処理を、別イベント (たとえば Application.Idle 時など)で実施するようリトライ処理を組み込んでみるとか。
|