タグ:VBA ( 4 ) タグの人気記事
(VBA)Excelでシートをコピー・削除
Excelでワークシートを複数コピーして、名前を変更し、セルに値を入れるサンプル(SheetCopyプロシージャ)です。
シート名は、For分のループ変数を使います。

また、SheetDelプロシージャはシートの削除を行ってます。


Public Const sBaseSheet = "Sheet1"
Public Const iMaxSheet = 4
 
Sub SheetCopy()
'ループ変数
Dim i As Integer
i = 0

Dim rng As Range
'コピー元のシートを選択
Worksheets("Sheet1").Select

'削除時の確認メッセージをOFFに
Application.DisplayAlerts = False
'画面高速化
Application.ScreenUpdating = False
For i = iMaxSheet To 1 Step -1
'シートをコピーする
ThisWorkbook.Sheets(sBaseSheet).Copy after:=Sheets(sBaseSheet)
'シートの名前をヘンコする
ThisWorkbook.Sheets(sBaseSheet & " (2)").Name = CStr(i)
'セルに値セット
Set rng = ThisWorkbook.Sheets(CStr(i)).Range("A1")
rng.Value = i
Next i
'削除時の確認メーッセージをOnに
Application.DisplayAlerts = True
'画面高速化
Application.ScreenUpdating = True
 
End Sub
 
Sub SheetDel()
Dim i As Integer
i = 0
Dim rng As Range
'削除時の確認メッセージをOFFに
Application.DisplayAlerts = False
'画面高速化
Application.ScreenUpdating = False
 
For i = iMaxSheet To 1 Step -1
'シート削除
ThisWorkbook.Sheets(CStr(i)).Delete
Next i
'削除時の確認メーッセージをOnに
Application.DisplayAlerts = True
'画面高速化
Application.ScreenUpdating = True
End Sub


参考:
ワークシートの追加 - ワークシートの追加 - Excel VBA入門
Office TANAKA - Excel VBA講座:シートの操作[シートを削除する]
Office TANAKA - Excel VBA Tips[ワークシートの名前を変更する]
[PR]
by Jehoshaphat | 2011-10-27 23:45 | VBA、マクロ | Trackback | Comments(0)
.Net(C#)アプリからExcelのVBAを呼び出したい(遅延バインディング)
.NetアプリからExcelのVBAを呼び出したい(事前バインディング) で参照設定からCOMのOffice操作DLLを呼び出す方法を書きました。(あらかじめ呼び出すオブジェクトのタイプライブラリを参照してコンパイル時に型チェックをするこの方法を事前バインディングと言います。)

しかしこの方法では参照設定したバージョンのExcelが入っているPCでしか実行できません。

対策としては、実行時にバインドする遅延バインディングを用います。

事前バインディングのコードと比較しながら遅延バインディングのコードを下記に書いてみます。
(コメント部分のコードが事前バインディングになります。)

using System.Runtime.InteropServices;
using System.Reflection;
 
public ExeMacro()
{
 
//Excelマクロファイルパス
string strMacroPath = @"D:\test.xls";
 
// Excel操作用COMオブジェクトを生成する
//ApplicationClass oExcel = new ApplicationClass();
object oExcel = CreateObject("Excel.Application");
 
//ワークブックコレクションオブジェクトを生成する。
//Workbooks oBooks = oExcel.Workbooks;
object oBooks = oExcel.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, oExcel, null);
 
//Excelファイルのオープン
//Workbook oBook = oBooks.Open(strMacroPath);
object oBook = oBooks.GetType().InvokeMember(
"Open", BindingFlags.InvokeMethod, null,
oBooks, new object[] {
strMacroPath
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
, Type.Missing
});
 
// Excelファイルの表示
//oExcel.Visible = true;
oExcel.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, oExcel, new object[] { true });
 
//マクロ実行(Testというサブプロシージャを実行する)
//oExcel.Run("Test");
oExcel.GetType().InvokeMember("Run", BindingFlags.InvokeMethod, null, oExcel, new object[] { "Test" });
 
//閉じる
//oBook.Close(false);
oExcel.GetType().InvokeMember("Quit", System.Reflection.BindingFlags.InvokeMethod, null, oExcel, null);
//COM解放
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oBook);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oBooks);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oExcel);
oBook = null;
oBooks = null;
oExcel = null;
}
 
/// <summary>
/// COMオブジェクトへの参照を作成および取得します
/// </summary>
/// <param name="progId">作成するオブジェクトのプログラムID</param>
/// <param name="serverName">
/// オブジェクトが作成されるネットワークサーバー名
/// </param>
/// <returns>作成されたCOMオブジェクト</returns>
public static object CreateObject(string progId, string serverName)
{
Type t;
if (serverName == null || serverName.Length == 0)
t = Type.GetTypeFromProgID(progId);
else
t = Type.GetTypeFromProgID(progId, serverName, true);
return Activator.CreateInstance(t);
}
 
/// <summary>
/// COMオブジェクトへの参照を作成および取得します
/// </summary>
/// <param name="progId">作成するオブジェクトのプログラムID</param>
/// <returns>作成されたCOMオブジェクト</returns>
public static object CreateObject(string progId)
{
return CreateObject(progId, null);
}


使い終わったら、Quitメソッドで、Excelファイルを閉じて、Marshal.FinalReleaseComObjectメソッドを使って、COMオブジェクトを必ず解放するようにしましょう。
上記のコードで事前と遅延バインディングの比較をしてもらうとわかるんですが、基本的に oExcel.GetType().InvokeMember メソッドでExcel内のメソッド実行したりプロパティを変更できるようです。(たしかに型が分からないわけですがら、リフレクションを使ってメソッド名やプロパティを指定しないといけませんね。)


VB.Netだとより簡単に遅延バインディング(実行時バインディング)ができるんですが、C#は結構面倒ですね。(VBはVB6時代から実行時バインディング使ってましたからね。)

参考:
(VB.Net)COMオブジェクトを解放する
MSサポート:Visual C# .NET で Office オートメーション サーバーをバインドする方法
とほほな日々 備忘録: Excel 遅延バインディング(LateBinding)
C#から遅延バインディングでEXCELのシート保護をする - とりあえずですけれども - 1981s
リフレクションを利用したレイトバインディングでExcelファイルを開く - Bug Catharsis
(続)リフレクションを利用したレイトバインディングでExcelファイルを開く - Bug Catharsis
Excelの解放: DOBON.NETプログラミング掲示板過去ログ
圧砕の雑記的な何か: 遅延バインディング
[PR]
by jehoshaphat | 2010-11-27 13:30 | .Net開発 | Trackback | Comments(0)
.Net(C#)アプリからExcelのVBAを呼び出したい(事前バインディング)
.NetアプリケーションからExcel2007のVBA(マクロ)標準モジュール内のサブプロシージャを呼び出す方法です。


まず、参照設定で、COMの Microsoft Excel 12.0 Object Library を追加します。
(12.0とかはExcelのバージョンで変わってきます。)

そして、下記のようなコードを書きます。(C#)
using Microsoft.Office.Interop.Excel;
 
//Excelマクロファイルパス
string strMacroPath = @"D:\test.xls";

 
//Excel操作用オブジェクト生成
ApplicationClass oExcel = new ApplicationClass();
//表示する
oExcel.Visible = true;
Workbooks oBooks = oExcel.Workbooks;

//Excelファイル開く
Workbook oBook = oBooks.Open(strMacroPath);
 
//マクロ実行(Testというサブプロシージャを動かす)
oExcel.Run("Test");
 
//終了処理(リソース解放)
oBook.Close(false);

System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
oBook = null;
 
System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);
oBooks = null;

 
oExcel.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
oExcel = null;

簡単ですね。といってもほぼ参考先まるままですが。。
しかし、この方法ではExcel2007が入っているPCでしか実行できません。
例えばExcel2003が入っているPCとかだと、エラーとなります。
ということで、どのバージョンでのExcelでも実行できる方法は次の記事で書きます。

参考:
全ては時の中に… : 【VB.NET】VB.NETからExcelのVBA(マクロ)を実行する
[PR]
by jehoshaphat | 2010-11-27 13:25 | .Net開発 | Trackback | Comments(0)
VBAのLine Input で改行コード(LF)が認識されない

あるC#アプリで、CSVファイル出力時に"\n"で改行を付け加えていました。

そのC#アプリで吐いたCSVを読み込む Excel のマクロを実行すと、C# で ¥n で付けてた改行が認識されません。

おかしいと思い、出力した CSV をバイナリエディタでみると改行コードが、0x0A(LF)だけになってました。。

Excel の VBA ではファイルを OPEN した後、下記のコードで1行ずつ読んでいました。
Line Input #intFF, recode

この Line Input はどうやら改行コード LF を解釈してくれず、改行を認識するのに CR(0x0D) が必要らしいです。

なので C# 側で、改行を ¥r¥n とするか、Environment.NewLine プロパティを使う方法が取れるようです。
(Environment.NewLineだとUNIX 以外のプラットフォームでは "¥r¥n" を含む文字列で UNIX プラットフォームでは "¥n" を含む文字を表すらしい)

参考
DOBON.NET:改行、タブ文字などの定数


C#側も直すべきですが、VBA側も何とかしたいと思って調べてみました。
すると、「Line Input # ステートメント」の仕様 - 鳶秋の日記というブログを発見。
なるほど、LF で Split して配列化すればいいようです。

ファイルサイズが大きいと危険と書いてますが、今回はサイズ小さいので大丈夫でしょう。。

参考:
改行コードに注意|VBA (マクロ) 作法/コーディング規約 集約中 ~ メタボなプログラムにサヨナラしよう
[PR]
by jehoshaphat | 2010-04-26 00:37 | VBA、マクロ | Trackback | Comments(0)