六帖のかたすみ

DVを受けていた男性。家を脱出して二周目の人生を生きています。自閉症スペクトラム(受動型)です。http://rokujo.org/ に引っ越しました。

.NETアプリケーションで遅延バインディングを使ってExcelのオートシェイプをコピー

Excelで画面上の文字にマルを付ける依頼があった。
それも、VBAからではなく、C#の.NETアプリケーションから。
しかも、バージョン違いを吸収するために、遅延バインディングを使え、と。
いろいろ試したところ、シートにマルのオートシェイプを作っておいて、それをコピペする方法でないと不可能と分かった。ところが参照したネット上のTipsは間違っていて、時間を食った。結局、素直にコピペ(Shape.Duplicate + Shape.Cut + WorkSheet.Paste)するのが一番良いとわかった。恐ろしく面倒なコードになった。


// Excelアプリケーションオブジェクト
private object xlsApplication = null;
// Workbooksオブジェクト
private object xlsBooks = null;

// Excelアプリケーションオブジェクト
protected object XlsApplication
{
get
{
// 存在しない場合は作成する
if (xlsApplication == null)
{
Type classType = Type.GetTypeFromProgID("Excel.Application");
xlsApplication = Activator.CreateInstance(classType);
}
return xlsApplication;
}
}

// Workbooksオブジェクト
protected object Workbooks
{
get
{
if (xlsBooks == null)
{
xlsBooks = XlsApplication.GetType().InvokeMember("Workbooks",
BindingFlags.GetProperty, null, XlsApplication, null);
}
return xlsBooks;
}
}

//あらかじめshapeSheetNameシートにitemNameというオートシェイプが作成されているものとして、
//sheetNameシートにnewItemNameという名前でオートシェイプを座標(x,y)にコピーする
public void CopyShape(int bookIndex, string sheetName, string shapeSheetName,
string itemName, string newItemName, float x, float y)
{
object book = null;
object sheets = null;
object sheet = null;
object shapeSheet = null;
object shapesFrom = null;
object shapesTo = null;
object shape = null;
object newShape = null;
object newShape2 = null;

try
{
// WorkBooksは
// WorkbooksオブジェクトからBookオブジェクトを取得
book = Workbooks.GetType().InvokeMember("Item", BindingFlags.GetProperty,
null, Workbooks, new object[]{ bookIndex });

// BookオブジェクトからSheetsオブジェクトを取得
sheets = book.GetType().InvokeMember("Worksheets", BindingFlags.GetProperty,
null, book, null);

// SheetsオブジェクトからSheetオブジェクトを取得
sheet = sheets.GetType().InvokeMember("Item", BindingFlags.GetProperty,
null, sheets, new object[]{ sheetName} );

// Shapeのあるシートをゲット
shapeSheet = sheets.GetType().InvokeMember("Item", BindingFlags.GetProperty,
null, sheets, new object[]{ shapeSheetName} );

//Shapeをゲッツ
shapesFrom = shapeSheet.GetType().InvokeMember("Shapes", BindingFlags.GetProperty,
null, shapeSheet, null);
shape = shapesFrom.GetType().InvokeMember("Item", BindingFlags.InvokeMethod,
null, shapesFrom, new object[] { itemName });

//コピペする
newShape = shape.GetType().InvokeMember("Duplicate", BindingFlags.InvokeMethod,
null, shape, null);
newShape.GetType().InvokeMember("Name", BindingFlags.SetProperty,
null, newShape, new object[] { newItemName });
newShape.GetType().InvokeMember("Cut", BindingFlags.InvokeMethod, null, newShape, null);
sheet.GetType().InvokeMember("Paste", BindingFlags.InvokeMethod,
null, sheet, null);

//配置
shapesTo = sheet.GetType().InvokeMember("Shapes", BindingFlags.GetProperty,
null, sheet, null);
newShape2 = shapesTo.GetType().InvokeMember("Item", BindingFlags.InvokeMethod,
null, shapesTo, new object[] { newItemName });
newShape2.GetType().InvokeMember("Left", BindingFlags.SetProperty,
null, newShape2, new object[] { x });
newShape2.GetType().InvokeMember("Top", BindingFlags.SetProperty,
null, newShape2, new object[] { y });
}
finally
{
//COMオブジェクトの掃除
ReleaseComObject(newShape2);
ReleaseComObject(newShape);
ReleaseComObject(shape);
ReleaseComObject(shapesTo);
ReleaseComObject(shapesFrom);
ReleaseComObject(shapeSheet);
ReleaseComObject(sheet);
ReleaseComObject(sheets);
ReleaseComObject(book);
}
}