Excel VBA: Hello Worldと変数、配列の宣言

ポツポツ使う場面が増えてきたので、備忘録代わりにまとめていこうかな(気が向いたときに)。

VBAでHello World

メニューバーからツール→マクロ→Visual Basic Editor(Alt+F11)をクリックするとエディタが起動します。最初は何もファイルが開かれていないと思うので、まず、メニューバーから挿入→標準モジュールをクリックして新規作成し、試しに以下のコードを打ち込んで実行してみます。

Sub helloWorld()
    MsgBox "Hello, VBA"
End Sub

入力し終わったらメニューの実行→Sub/ユーザー フォームの実行(F5)をクリックするとスクリプトが実行されます。結果は下図のようになります。
vba_hello_world
ダイアログボックス内に文字列が表示されていますね。仮に下記のようにした場合は、

Sub helloWorld()
    MsgBox "Hello, VBA"
    MsgBox "Hello, Excel"
End Sub

一つ目の”Hello, VBA”のダイアログのOKを押した後、”Hello, Excel”のダイアログが表示されます。どうやらMsgBox関数はブロック関数みたい。

変数の宣言 – Dim

Sub varTest()
    Dim num1 As Integer
    Dim str1 As String
    Dim num2 As Integer, str2 As String

    num1 = 10
    str1 = "文字列1"

    MsgBox num1 & " " & str1
    MsgBox num2 & " " & str2, vbInformation, "デバッグプリント"
End Sub

実行結果は
vba_var01
vba_var02

変数宣言の一般式は

Dim <変数名> As <型>

のようにDim~Asステートメントを用います。

また、MsgBox関数のvbinformationを指定することで情報メッセージアイコンを表示します。ちなみに、出力する複数の文字列の連結は「&」を用います。

定数の宣言 – Const

Const <定数名> As <型> = <値>

変数宣言と似てますね。異なるところは、DimがConstに変わり、宣言と値の初期化を同時に行うことですかね。変数も値の初期化は可能ですが、それは任意です。

オブジェクトの参照を変数に格納 – Set

オブジェクトの参照を代入する際にはSetステートメントを使用します。以下のコードは1つ目のワークシート名を表示しています。

Sub objectTest()
    Dim tmpSheet As Worksheet
    Set tmpSheet = Worksheets(1)
    MsgBox tmpSheet.Name, vbInformation
End Sub

実行結果は
vba_var_set01
一般式は

Set <オブジェクト型変数> = <オブジェクト>

コンパイルエラー、「SubまたはFunctionが定義されていません」の原因

大抵ミスタイプです。Worksheets(1)と打つところをWorksheet(1)としてしまうとか。変数宣言のミスでもデフォルトでは「SubまたはFunctionが~」と出力されるので注意。

配列の宣言

Dim <配列名>(<要素数>) As <型>

Sub objectTest()
    Dim arr(3) As Integer
    arr(0) = 99
    MsgBox arr(0)
End Sub

ダイアログには99が表示されます。配列の添え字は0から数えますが、下記の文をモジュールの宣言セクションに書くことで1から数えられます。

Option Base 1

Option Base 1

Sub objectTest()
    Dim arr(3) As Integer
    arr(1) = 99
    MsgBox arr(1)
End Sub

実行結果は同じく99です。

Posted in Excel VBA | Tagged , | Leave a comment

Words of the Day – Thursday March 19, 2009

1. I can assure you that I will make the new application.
2. Let go of my redundant emotions.

Posted in Words of the Day | Tagged , | Leave a comment

Java: イベント駆動によるModelとViewの分離 – Observer パターン

よくGUIやWebアプリの簡単なサンプルソースなどは、UIとアプリケーションのロジックが同じクラスまたはメソッドに書かれている場合が多いです。それはそのサンプルがある特定の機能や関数の紹介の為に簡潔に書いているのですが、仮にいざそのソースを元にアプリを作りこんで機能の追加を行っていくとUIとアプリのロジックは分離したほうが保守・拡張と共に行いやすいです。

下記のプログラムは1秒毎に数値をカウントし、それを2進数と10進数でGUI上のラベルに出力する機能をモデルとビューに分けています。すなわち、数値のカウントをするモデルと数値をUIに表示するビューに。(いくつかの言語ではGUIの部品としてタイマーがあるようですが。。)

実行結果

count_timer01

クラス図

countmodel_view_class

インスタンスの生成はコンストラクタで行うのがいいのですが、はしょっています。さて、これまでに何らかのフレームワークを使っていた方には上クラス図はMVCの説明図として見慣れているかもしれません。今回ModelとViewを繋ぐControllerの役割はCountListenerが担っています(下記コードではCountChangeEvent経由でModelインスタンスを渡すのみですが)。

処理手順

ビュー側で自身のインスタンスをモデルに登録し(モデル.addCountListener(ビュー))、モデルのデータが更新された場合、モデル→ビューへイベントを送出。イベント内部にモデルのデータがあり、そのデータでビューがUIを更新します。イベントの発生順序等は下図のシーケンス図のようになります。

シーケンス図

countmodel_view_sequence

無限ループに注意

ビューを更新するイベントリスナーのメソッド(ここではcountChanged())で再度モデルのプロパティ変更メソッド(ここではsetCount())を用いると、再度イベント通知処理(notifyToListeners())が発生することで、無限ループになるので注意が必要です。

ビューの追加手順

ビューを追加する際の手順は、ビューのインスタンスをモデルのリスナーに登録し(addCountListener())、ビュー自身がリスナーのメソッドを実装することで(countChanged())、モデルからのイベントを受け取ることが出来ます。

そういえば最近はIDEの方でバインド設定したり、ObservableList等があるのであまり意識することがなくなってきたなぁ。

ソースコード

import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;

class CountView extends JFrame implements CountListener{

	private final JLabel binaryLabel = new JLabel("0");
	private final JLabel decimalLabel = new JLabel("0");
	private CountModel cModel = new CountModel(0);

	public static void main(String[] args) {
		new CountView();
	}

	public CountView() {
		super("Counter");
		Container c = getContentPane();
		c.setLayout(new GridLayout(2, 2));
		c.add(new JLabel(" 2進数:"));
		c.add(binaryLabel);
		c.add(new JLabel("10進数:"));
		c.add(decimalLabel);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		cModel.addCountListener(this); // ModelにViewを登録

		pack();
		setVisible(true);
	}

	public void countChanged(CountChangeEvent e) {
		if (e.getSource() == cModel) {
			binaryLabel.setText(Integer.toString(cModel.getCount(), 2));
			decimalLabel.setText(Integer.toString(cModel.getCount(), 10));
		}
	}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * カウントするModel
 */
public class CountModel {

	private int count;
	private final List<CountListener> listeners = new ArrayList<CountListener>();
	private Timer t = new Timer("Count Timer", false);

	CountModel(int i) {
		count = i;
		t.scheduleAtFixedRate(new CountTime(), 0, 1000);
	}

	// Viewを登録
	public void addCountListener(CountListener listener) {
		listeners.add(listener);
	}

	public int getCount() {
		return count;
	}

	public void setCount(int i) {
		count = i;
		notifyToListeners();
	}

	// Viewへの通知
	private void notifyToListeners() {
		for (CountListener listener : listeners) {
			listener.countChanged(new CountChangeEvent(this));
		}
	}

	class CountTime extends TimerTask {
		@Override
		public void run() {
			setCount(getCount() + 1);
		}
	}
}
/**
 * View側で実装する(Model側から呼び出し)
 */
public interface CountListener {
	public void countChanged(CountChangeEvent e);
}

/**
 * 通知内容を表すイベント(Modelが生成しViewが受け取る)
 */
public class CountChangeEvent {
	private final CountModel source;

	public CountChangeEvent(CountModel count) {
		this.source = count;
	}

	public CountModel getSource() {
		return source;
	}
}
Posted in Java | Tagged , , , , | Leave a comment

Java, デザインパターン: Simple Factory – インスタンスの生成方法を任せる

以前デザインパターンの理解の確認がてら簡単なコードを書いていたので投稿してみます。リファクタリングの前後を省いているので初見ではパターンのメリットと適応基準が見えにくく、またサンプルのテーマ設定が良くなかったのでイマイチ説明し難い(反省)。今回のようなToyコードみたいなのはたまに書くのですが、Blog記事としてまとめるのが手間で大抵HDDの片隅に眠ってしまうのですが、今後はとりあえず上げていこうかと思います。説明などは隙をみて書き足していく感じでまず投稿、みたいな。ただ、そればっかりだと後で自分が読んだときに分からなくなるので、ほどほどにしよう。

クラス図

simple_factory_classes

文字列の分割プログラム。

入力: クラス名+<区切り文字>+メソッド名の文字列
出力: その文字列の分割結果が格納されたインスタンス(Namerクラス)。

文字列の形式が”<クラス名>#<メソッド名>”か”<クラス名>.<メソッド名>”によって、すなわち区切り文字によって分割処理のメソッドの内容が変わるので、その違いを派生クラスでオーバーライドして定義したメソッドで吸収しようというもの。

これによる利点はMain側が分割対象の文字列の形式を意識しなくてよいこと。単にNameFactory#getNamer()に渡すだけ。文字列の形式が2つの内のどちらで、どのクラスに処理を任せるかの処理はgetNamer()が行う。これによって、仮に文字列の形式を増やす場合に修正するのはgetNamer()のifブロック、追加するのは新しい派生クラス。

ソースコード

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        NameFactory nameFactory = new NameFactory();
        Namer namer;
        namer = nameFactory.getNamer("String#indexOf()");
        printName(namer);
        namer = nameFactory.getNamer("ArrayList.get()");
        printName(namer);
        namer = nameFactory.getNamer("Thread#run()");
        printName(namer);
    }

    private void printName(Namer namer) {
        System.out.println("Class  Name: " + namer.className);
        System.out.println("Method Name: " + namer.methodName);
    }

}

public class NameFactory {
    // 区切り文字の種類によって、処理する派生クラスを決める
    public Namer getNamer(String input) {
        if (input.indexOf(".") > 0)
            return new PeriodNamer(input);
        else if (input.indexOf("#") > 0)
            return new SharpNamer(input);
        return null;
    }
}

public class Namer {

    protected String className;
    protected String methodName;

    public String getClassName() {
        return className;
    }

    public String getMethodName() {
        return methodName;
    }
}

public class SharpNamer extends Namer {
    // 「#」で名前を区切る
    public SharpNamer(String str) {
        int i = str.lastIndexOf("#");
        if (i > 0) {
            className = str.substring(0, i); // (beginIndex, endIndex)
            methodName = str.substring(i + 1); // (beginIndex)
        } else {
            className = "";
            methodName = str;
        }
    }
}

public class PeriodNamer extends Namer {
    // 「.」で名前を区切る
    public PeriodNamer(String str) {
        int i = str.lastIndexOf(".");
        if (i > 0) {
            className = str.substring(0, i); // (beginIndex, endIndex)
            methodName = str.substring(i + 1); // (beginIndex)
        } else {
            className = "";
            methodName = str;
        }
    }
}

実行結果

Class  Name: String
Method Name: indexOf()
Class  Name: ArrayList
Method Name: get()
Class  Name: Thread
Method Name: run()

書いた後ふと考えたのですが、これ100形式だと100派生クラスで、if-elseブロックもえらいことになるなぁ。こういう時、現時点では思考停止してしまうので、今月の課題。

今後はなるべく制作中のアプリの中での問題かそれに関わるもの、絡められるものを取り上げていきたい。

Posted in Java | Tagged , , | 1 Comment

Java, JSP: 現在時刻が指定期間内か判定する – GregorianCalendar#before、after

日時を扱うクラスはDateとGregorianCalendarがありますが、Sunは後者を推奨しているようです。実際GregorianCalendarのほうが扱いやすいです。下のサンプルは、現在時刻が指定した期間内か否かを判定するものです。

ソースコード

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="java.util.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <%!
    final int MONTH_OFFSET = 1;

    String showTime(Calendar cal) {
      String str;
      str = cal.get(Calendar.YEAR) + "/"
        + (cal.get(Calendar.MONTH) + MONTH_OFFSET)  + "/"
        + cal.get(Calendar.DATE) + " "
        + cal.get(Calendar.HOUR) + ":"
        + cal.get(Calendar.MINUTE);
      return str;
    }

    boolean isPeriod(Calendar start, Calendar end) {
      Calendar cur = Calendar.getInstance();
      return cur.after(start) && cur.before(end);
    }
  %>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Date Comparison</title>
    </head>
    <body>
        <h1>JSP Date Comparison</h1>
    <%
      // (year, month, date, hour, minute) monthの範囲は0-11で1月は0
      Calendar startTime = new GregorianCalendar(2009, 2 - MONTH_OFFSET, 23, 21, 0);
      Calendar endTime = new GregorianCalendar(2009, 2 - MONTH_OFFSET, 23, 21, 10);

      out.println("開始時刻: " + showTime(startTime) + "<br />");
      out.println("終了時刻: " + showTime(endTime) + "<br />");

      if (isPeriod(startTime, endTime)) {
        out.println("現時刻は指定期間「内」");
      } else {
        out.println("現時刻は指定期間「外」");
      }
    %>
    </body>
</html>

日時の比較はGregorianCalendar#after、beforeメソッド以外にint compareTo(Calendar cal)等もあります。
実際に使う際、期間を指定するGregorianCalendarのコンストラクタの引数データは他の入力から受け取るようにします。

実行結果例

本日の21:05に計ると…

JSP Date Comparison
開始時刻: 2009/2/23 9:0
終了時刻: 2009/2/23 9:10
現時刻は指定期間「内」

追記: SimpleDateFormatによる出力の整形

d_kamiさんに改良していただきました。ありがとうございます(^-^)

String showTime(Calendar cal) {
Date date = cal.getTime();
SimpleDateFormat format = new SimpleDateFormat(“yyyy/MM/dd HH:mm”);
return format.format(date);
}
と書けばすっきりするよ、import java.text.SimpleDateFormatを忘れずに – SimpleDateFormat – マイペースなプログラミング日記

showTimeを修正して計りなおした実行結果は、

開始時刻: 2009/02/23 21:00
終了時刻: 2009/02/24 21:10
現時刻は指定期間「内」

確かに出力はyyyy/MM/dd HH:mmの形式になっていて見栄えも良いです。

参考サイト

Posted in Java | Tagged , , , | 1 Comment

Java, Swing: JComponentのGraphicsオブジェクトを用いて直線を描画

JComponentはほとんど全てのSwing コンポーネントの基底クラスで、Graphicsオブジェクトも持っています。下記のソースは、そのGraphicsを用いて画面に直線を描画するものです。

ソースコード

package linecomp;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class LineComp extends JComponent {

  public static void main(String[] args) {
    Runnable myGUI = new Runnable() {
      @Override
      public void run() {
        JFrame win = new JFrame("Line Component");
        win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Insets ins = win.getInsets();
        win.setSize(300 + ins.left + ins.right, 300 + ins.top + ins.bottom);
        win.add(new LineComp());
        win.setVisible(true);
      }
    };
    SwingUtilities.invokeLater(myGUI); // 保留中のすべての AWT イベントが処理されたあとに発生
  }

  @Override
  public void paintComponent(Graphics g) {
    g.setColor(getBackground());
    g.fillRect(0, 0, getWidth(), getHeight());
    g.setColor(Color.RED);
    g.drawLine(0, 0, getWidth(), getHeight());
  }
}

GUI部品の(再)描画レンダリングが発生した際、オーバーライドしたpaintComponent()内の手続きをEventQueueに登録しEDT(Event Dispatch Thread)が処理をします。標準のGUI部品をカスタマイズしたい場合などに使えます。その場合は予めsuper.paintComponent(g);でデフォルトのレンダリングを基底クラスに任せ、その後にカスタムの描画処理を書きます。

実行結果

JComponent に線を描画

追記: d_kami さんに改良して頂きました

InsetとJFrame#setSizeを使わずにJComponent#setPreferredSizeとJFrame#packを使うようにした – 他のやり方 – マイペースなプログラミング日記

comp.setPreferredSize(new Dimension(300, 300));
win.add(comp);
win.pack();

確かにsetPreferredSizeでコンポーネントのサイズを直接指定したほうが今プログラムの文脈に沿っています。私のほうはコンポーネントでなくJFrameのサイズの指定ですから。また、オーバーライドしたpaintComponent()でgetWidth()やgetHeight()を二度使うのであれば、一度ローカル変数に格納することでオーバヘッドを下げるのも大切ですね。日頃からの習慣にしないと。
とても勉強になりました。ありがとうございます。

参考サイト

Posted in Java | Tagged , , | 1 Comment

NetBeans から Subversion でコミットをする際のエラーの解決法の一例

Windows版NetBeans6.5でソースをインポートまたはコミットする際に以下のようなエラーが発生する場合があります。

‘.’ is not a working copy Can’t open file ‘.svn/entries’: No such file or directory

これはNetBeansが使用するsvnクライアントがcygwinのものだった場合に生じるエラーのようです。

未だcygwin環境のsvn以外のsvnをインストールしていない場合は下のアドレスからダウンロードしてください。
subversion: Subversion Packages
その後、メニューバーの「ツール」→「オプション」から設定画面を開いて、「その他」タブ→「バージョン管理」画面のSubversion画面を開きます。左にあるリストメニューからSubversionを選択し、最初の設定項目である「SVN実行可能ファイルパス」を設定すれば正常にインポート、コミットできるようになります。

ちなみに、cygwinのでなければ↑のsvnパッケージでなくともOKのようです。

参考サイト

  • Nabble – Netbeans IDE Users – Problems with SVN, svn/entities file doesn’t exists
Posted in Java | Tagged , , , | Leave a comment

Twitterを英語の学習ツールにしてみる

Twitterにその日の学習ログを残してみようかな。そして、その学習ログをWordPress のプラグインでこのブログに週に一回落とし込んで確認してみようかな。

学習ログの形式は例えば以下のようにします。
[word] <単語> : <日本語の意味>
例文は,
[e.g.] <例文> : <日本語訳>
音読とかした場合は、
[<テキスト名(の略でもOK)>] <章番号1>, <章番号2>… : 音読-X回, オーバーラップ-Y回, シャドウイング-Z回
みたいに。

とりあえず1週間試してみます。その内飽きるだろうけれど。
https://twitter.com/yukun_

あと、遅くなりましたが、
あけましておめでとうございます。
本ブログ記事が貴方にとって有益な情報であれば幸いです。今年もよろしくお願いします。

昨年からぽつぽつとCSネタを書いてきましたが、今年は英語学習に力を入れるため昨年より頻度が落ちるかと思います。

Posted in Days | Tagged , , | Leave a comment

TKGとは?

今日、体育会系(卓球部)の人と朝食の話していたら「今日はTKGで済ませたよ」と。TKG?
これは「(T)卵(K)かけ(G)ご飯」の略だそうです。いやーその定番メニューを頭3文字直す発想がおもしろい。なるほど「たまごかけごはん」より「TKG」の方が確かに言いやすいかも。となると「なっとうかけごはん」は「NKG」か。

Posted in Days | Tagged , | Leave a comment

Apacheでよく使うコマンドと設定項目

設置環境はFedoraを想定しています。
注:ソースからインストールした場合や他の環境だと一部ファイルのパスが違うところがあります。
今後も少しずつ書き足し・修正していきます。

コマンド

起動
# /etc/rc.d/init.d/httpd start
または、
# service httpd start
終了
# /etc/rc.d/init.d/httpd stop
または、
# service httpd stop
再起動
# /etc/rc.d/init.d/httpd restart
または、
# service httpd restart
自動起動に設定
# chkconfig httpd on
自動起動の確認(Run level 3:on)
# chkconfig –list httpd
設定の反映
# /etc/rc.d/init.d/httpd reload
ディレクトリの所有者の変更
# chown <ユーザ名>. /var/www/html/
ディレクトリをApache実行ユーザに変更
# chown -R apache:apache /var/www/html/cgi-bin/

httpd.confの設定

設定ファイルhttpd.confのパス
/etc/httpd/conf/httpd.conf
外部設定ファイル*.confを置くパス
/etc/httpd/conf.d/*.conf
・起動時に読み込まれる
・AliasとDirectoryを合わせて用いる場合が多い
DocumentRoot
ルートディレクトリの設定
e.g. DocumentRoot “/var/www/html” で
www.example.com/へのアクセスは/var/www/htmlのインデックスページとなる。
Alias
Alias <ドメイン以下のURLパス> <サーバ内のディレクトリパス>
e.g. Alias /blog /var/www/blog
の場合は、http://www.example.com/blog/にアクセスした際、サーバの/var/www/blog/内の既定のインデックスファイルが読み込まれる。
Directoryタグ

e.g.

<directory "/var/www/html">〜<directory>

属性にディレクトリパスを指定している。

.htaccessを許可する場合
AllowOverride All
IPアドレスによるアクセス制限
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
Allow from 192.168.1.0/24

↑はlocalhost、イントラネット以外からのアクセスを拒否

.htaccessによるパスワード認証

.htaccessファイル内の設定例

SSLRequireSSL # SSL経由のアクセス
AuthUserFile <認証するユーザリストのパス>
AuthGroupFile <パス>
AuthName "<ページ名>"
AuthType Basic # 認証タイプ
require valid-user

認証するユーザの登録

初回は
# htpasswd -b -c <保存先> <ユーザ名> <パスワード>
二件目以降は既にファイルが作成されているので-cを抜く
# htpasswd -b <保存先> <ユーザ名> <パスワード>
ここで作成したファイルのパスを上のAuthUserFile項目に書く。

Posted in Linux | Tagged , , , , | 1 Comment