2009年6月6日土曜日

[.NET]QRコードの変換

[はじめに]
・最近、仕事でQRコードを扱うシステム開発に携わる機会が多いので、
 .NETでも作ってみました。
 .NET FrameworkではQRコードを標準でサポートしていない為、
 外部のコンポーネントを利用しています。

[関連情報]
QRコードの仕様 (デンソーウェーブのサイト)
 http://www.qrcode.com
外部コンポーネント
 「ThoughtWorks.QRCode.dll」を参照しています。
 [Open Source QRCode Library]
からダウンロードできます。
 「ThoughtWorks.QRCode.dll」を参照は、「参照設定」から追加して下さい。
 (※追加しないとコンパイルエラーになります。)
  参照設定

[ソース]
 QRコードの変換ユーティリティクラスです。
 提供するメソッドは、以下の2つです。
 ・Encodeメソッド:文字列をQRコードのイメージに変換する。
 ・Decodeメソッド:QRコードのイメージから文字列を取得する。
Imports System.IO
Imports System.Text
Imports ThoughtWorks.QRCode.Codec
Imports ThoughtWorks.QRCode.Codec.Data
Imports ThoughtWorks.QRCode.Codec.Util

''' <summary>
''' QRコード関連のユーティリティ
''' </summary>
''' <remarks></remarks>
Public NotInheritable Class QRCodeUtil

    '[説明]
    '[参照設定]
    '   ThoughtWorks.QRCode.dll
    '  上記DLLは、以下のサイトよりダウンロード可能
    '  [Open Source QRCode Library]
    '  [http://www.codeproject.com/KB/cs/qrcode.aspx]
    '[QRコードの仕様]
    '   デンソーウェーブの下記サイトをご参照下さい。
    '   [QR Code.com]
    '   [http://www.qrcode.com]


    ''' <summary>
    ''' デフォルトのエンコーディング名
    ''' </summary>
    ''' <remarks></remarks>
    Private Const DEFAULT_ENCODING_NAME As String = "shift_jis"

    ''' <summary>
    ''' デフォルトのエンコーディング
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared ReadOnly DEFAULT_ENCODING As Encoding _
             = Encoding.GetEncoding(DEFAULT_ENCODING_NAME)

#Region "文字列をQRコードに変換する。"

    ''' <summary>
    ''' 文字列をQRコードに変換する。
    ''' </summary>
    ''' <param name="txtData">変換元の文字列</param>
    ''' <param name="encMode">情報の種類(Byte/AlphaNumeric/Numeric)</param>
    ''' <param name="errCorrect">誤り訂正能力(L/M/Q/H)</param>
    ''' <param name="scale">1セル当りのピクセル数</param>
    ''' <param name="version">QRコードに格納する情報量を決める型番(1~40)</param>
    ''' <returns>QRコードのイメージ</returns>
    ''' <remarks></remarks>
    Public Shared Function Encode( _
        ByVal txtData As String, _
        ByVal encMode As QRCodeEncoder.ENCODE_MODE, _
        ByVal errCorrect As QRCodeEncoder.ERROR_CORRECTION, _
        ByVal scale As Integer, _
        ByVal version As Integer _
        ) As Image

        Return Encode( _
            txtData, encMode, errCorrect, _
            scale, version, DEFAULT_ENCODING)
    End Function


    ''' <summary>
    ''' 文字列をQRコードに変換する。
    ''' </summary>
    ''' <param name="txtData">変換元の文字列</param>
    ''' <param name="encMode">情報の種類(Byte/AlphaNumeric/Numeric)</param>
    ''' <param name="errCorrect">誤り訂正能力(L/M/Q/H)</param>
    ''' <param name="scale">1セル当りのピクセル数</param>
    ''' <param name="version">QRコードに格納する情報量を決める型番(1~40)</param>
    ''' <param name="encoding">エンコーディング</param>
    ''' <returns>QRコードのイメージ</returns>
    ''' <remarks></remarks>
    Public Shared Function Encode( _
        ByVal txtData As String, _
        ByVal encMode As QRCodeEncoder.ENCODE_MODE, _
        ByVal errCorrect As QRCodeEncoder.ERROR_CORRECTION, _
        ByVal scale As Integer, _
        ByVal version As Integer, _
        ByVal encoding As System.Text.Encoding _
        ) As Image

        Dim errMsg As String = Nothing

        Dim qrEnc As QRCodeEncoder = Nothing
        Dim img As Image = Nothing

        '引数チェック
        '[変換元の文字列]
        '   Nothingと空文字列はNGとする。
        If String.IsNullOrEmpty(txtData) Then
            Throw New ArgumentException( _
                "Encode#txtDataが、Nothingか空文字列です。")
        End If

        '[QRコードに格納する情報量を決める型番]
        '   1~40の範囲外はNGとする。
        If version < 1 OrElse version > 40 Then
            errMsg = String.Format( _
                "Versionが範囲外[1~40]です。値:[{0}]", version)
            Throw New ArgumentOutOfRangeException( _
                "Encode#version", errMsg)
        End If

        qrEnc = New QRCodeEncoder()

        '「情報の種類」を設定
        '   QRCodeEncoder.ENCODE_MODE.BYTE
        '   QRCodeEncoder.ENCODE_MODE.NUMERIC
        '   QRCodeEncoder.ENCODE_MODE.ALPHA_NUMERIC
        qrEnc.QRCodeEncodeMode = encMode

        '「誤り訂正能力」を設定
        '   QRCodeEncoder.ERROR_CORRECTION.L
        '   QRCodeEncoder.ERROR_CORRECTION.M
        '   QRCodeEncoder.ERROR_CORRECTION.Q
        '   QRCodeEncoder.ERROR_CORRECTION.H
        qrEnc.QRCodeErrorCorrect = errCorrect

        '「1セル当りのピクセル数」を設定
        '   数値が大きい程、画像のサイズは大きくなる。
        qrEnc.QRCodeScale = scale

        '「QRコードに格納する情報量を決める型番」を設定
        '   1から40までの整数を指定
        '   格納するデータ長が長い程、
        '   より大きいバージョン番号を必要とする。
        '   QRコードを構成するセルの数も多くなる。
        qrEnc.QRCodeVersion = version

        img = qrEnc.Encode(txtData, encoding)

        Return img
    End Function
#End Region

#Region "QRコードのイメージから文字列を復元する。"

    ''' <summary>
    ''' QRコードのイメージから文字列を復元する。
    ''' </summary>
    ''' <param name="imgData">QRコードのイメージ</param>
    ''' <returns>復元後の文字列</returns>
    ''' <remarks></remarks>
    Public Shared Function Decode( _
        ByVal imgData As Image _
        ) As String
        Return Decode(imgData, DEFAULT_ENCODING)
    End Function


    ''' <summary>
    ''' QRコードのイメージから文字列を復元する。
    ''' </summary>
    ''' <param name="imgData">QRコードのイメージ</param>
    ''' <param name="encoding">エンコーディング</param>
    ''' <returns>復元後の文字列</returns>
    ''' <remarks></remarks>
    Public Shared Function Decode( _
        ByVal imgData As Image, _
        ByVal encoding As System.Text.Encoding _
        ) As String

        Dim qrDec As QRCodeDecoder = Nothing
        Dim qrBitmap As QRCodeBitmapImage = Nothing
        Dim txtData As String = Nothing

        '引数チェック
        '[変換元の文字列]
        '   NothingはNGとする。
        If imgData Is Nothing Then
            Throw New ArgumentNullException( _
                "Decode#imgDataがNothingです。")
        End If

        qrDec = New QRCodeDecoder()
        qrBitmap = New QRCodeBitmapImage(New Bitmap(imgData))

        txtData = qrDec.decode(qrBitmap, encoding)

        Return txtData
    End Function

#End Region

End Class
[VB.NET]QRコードの変換ユーティリティ

2009年5月24日日曜日

[.NET]データベースの接続文字列の書式を簡単に知るには?

[はじめに]
・.NETのアプリケーションからデータベースに接続する場合、
 接続文字列という情報が必要になります。(.NETに限った話ではありませんが…)
 .NETのアプリケーション開発で、接続文字列の書式が分からない場合、
 書籍やインターネット、他のアプリケーションを参考にすることがありますが、
 「Visual Studio 2008」の機能を使って、接続文字列を簡単に取得する方法があります。
 (※「Visual Studio 2008」とありますが、
   「Visual Studio.NET 2002」、「Visual Studio.NET 2003」、
   「Visual Studio 2005」でも可能です。
   試していないので若干方法が異なると思いますがご了承下さい。)

[前提条件]
・「Visual Studio 2008」がインストールされていること。
・データベースにアクセスできること。

[手順]
(1)「Visual Studio 2008」を起動し、「サーバーエクスプローラ」を選択します。
  (※「サーバーエクスプローラ」が表示されない場合は、「ツール」から表示可能にできます。)
sql2005_01.JPG

(2)「データ接続」を右クリックし、「接続の追加」を選択します。
sql2005_02.JPG

sql2005_03.JPG

(3)「データソースの変更」画面で、「データソース」や「データプロバイダ」を選択します。
  選択する内容は、接続するデータベースの種類によって変わります。
  ここでは、「SQL Server 2005 Express Edition」に接続する例として、
  「データソース」に「Microsoft SQL Server」、
  「データプロバイダ」に「.NETFrameworkSQLServer用データプロバイダ」を選択します。
sql2005_04.JPG

(4)「接続の追加」画面で、接続情報を入力します。
  ここでは、
  ・接続先のサーバを「(local)」、
  ・認証方式を「Windows認証」、
  ・接続先データベースを「master」
  とします。
 接続情報を入力したら、「テスト接続」ボタンを押して、
 データベースの接続がうまく行えることを確認します。
sql2005_05.JPG

(5)データベースの接続が成功したら、確認画面が表示されます。
  確認メッセージを「OK」ボタンで閉じ、
  「詳細設定」ボタンを押し「詳細プロパティ」画面を表示します。
sql2005_06.JPG

(6)「詳細プロパティ」画面の一番下の欄に、接続文字列が表示されます。
  通常のテキストなので、コピーして流用することもできます。
  この場合の書式文字列は、
  「Data Source=(local);Initial Catalog=master;Integrated Security=True」
  です。
sql2005_07.JPG

[関連サイト]
(1)接続文字列の使用
 http://msdn.microsoft.com/ja-jp/library/ms254978(VS.80).aspx

2009年5月17日日曜日

[Toy's Review]電子ブロック

(1)レビュー
 学研より発売された電気実験キットです。
 抵抗、トランジスタ、ダイオード、豆電球等のパーツが、
 ブロックになっており、組み立てるだけで、
 簡単に電気回路を組み立てることができます。

 私は小学校3年の頃にクリスマスプレゼントで買ってもらいましたが、
 予め回路の組立て例が用意されているので、
 小学生でも充分楽しめる内容でした。

 部品の意味を知らなくても、
 電子ブザーや簡易ラジオを簡単に組み立てられる。
 これが電子ブロックの醍醐味だと思います。

 1981年に生産が中止になりましたが、
 「大人の科学」シリーズとして復刻版が発売されたようです。

 「大人の科学」とありますが、子供でも充分楽しめると思います。
 子供の理系離れが進んでいる昨今、薦めてみてはどうでしょうか?
 
(2)リンク
大人の科学 学研電子ブロックEX-150

大人の科学 学研電子ブロックEX-150

  • 出版社/メーカー: 学研
  • メディア: おもちゃ&ホビー
大人の科学 製品版 新装版 電子ブロックEX150

大人の科学 製品版 新装版 電子ブロックEX150

  • 出版社/メーカー: 学研
  • メディア: おもちゃ&ホビー
大人の科学 学研電子ブロックEX150

大人の科学 学研電子ブロックEX150

  • 出版社/メーカー: 学研
  • メディア: おもちゃ&ホビー
大人の科学 学研電子ブロックEX150

大人の科学 学研電子ブロックEX150

  • 出版社/メーカー: 学研
  • メディア: おもちゃ&ホビー
大人の科学 学研電子ブロックEX150入門セット

大人の科学 学研電子ブロックEX150入門セット

  • 出版社/メーカー: 学研
  • メディア: おもちゃ&ホビー
大人の科学 電子ブロックDXパック210

大人の科学 電子ブロックDXパック210

  • 出版社/メーカー: 学研
  • メディア: おもちゃ&ホビー
大人の科学シリーズ マイキット150復刻版

大人の科学シリーズ マイキット150復刻版

  • 出版社/メーカー: 学研
  • メディア: エレクトロニクス

2009年5月2日土曜日

[Game's Review]クイズマジックアカデミーDS(通常版)

(1)レビュー
 一時期ゲーセンではまっていて、
 いつかはDSで出て欲しいなと思っていましたが、ようやくでました。

 このゲームの醍醐味はやはり対戦でしょう !!
 自宅に無線LANの環境があれば、全国のプレイヤーと対戦ができます。
 しかし、相手も同じゲームを持っていないとできないのが残念(>_<)
 ダウンロード対戦もありにして欲しかったなぁ。。。

 最新のクイズの問題がサーバーから配信されるので、
 インターネット経由でダウンロードして、常に最新のクイズを楽しめます! 

(2)リンク
クイズマジックアカデミーDS(通常版)

クイズマジックアカデミーDS(通常版)

  • 出版社/メーカー: コナミデジタルエンタテインメント
  • メディア: Video Game

[Game's Review]ドラゴンクエストV 天空の花嫁(DS版)

(1)レビュー
 [DS版オリジナルの要素]
 ・花嫁候補が3人になった。
  ビアンカ、フローラに加えて、デボラが追加!
 ・すれちがい通信でオリジナル名産品集めが楽しめる。
  DSを閉じてかばんの中とかに入れておくだけで、
  ドラクエ5を持っている人とすれ違うと勝手に通信します。  
  他の人と通信するとお互いが作った『名産品』を交換するというもの。
  交換して受け取った名産品は専用の展示室に飾られます。

 モンスターを仲間にするシステムは従来通りです。
 以下は、はぐれメタルを仲間にした時の写真です。
 228匹目でグランバニアの洞窟で仲間にしました。
 はぐれメタル(その1)
 はぐれメタル(その2)

(2)リンク
ドラゴンクエストV 天空の花嫁

ドラゴンクエストV 天空の花嫁

  • 出版社/メーカー: スクウェア・エニックス
  • メディア: Video Game

[Game's Review]ドラゴンクエストIV 導かれし者たち(DS版)

(1)レビュー
 ドラクエ4は、ファミコン、プレステでプレイしましたが、
 思わず買ってしまいました!!

 リニューアル版では、プレステ版同様、6章までありますが、
 若干内容が異なります。

 裏ダンジョンは、ドラクエ8でお馴染みのあの二人組がでてきます(笑)

(2)リンク
ドラゴンクエストIV 導かれし者たち

ドラゴンクエストIV 導かれし者たち

  • 出版社/メーカー: スクウェア・エニックス
  • メディア: Video Game

[Game's Review]ドラゴンクエストVIII 空と海と大地と呪われし姫君

(1)レビュー
 本シリーズ初の3D対応のゲームです。

 従来シリーズは「上から見下ろす視点」でしたが、
 今作は「主人公視点」となることで、
 あたかも自分がフィールドを歩いたり洞窟を探検しているかのような
 感覚で楽しめました。
 「あたかも自分が~」ってところが、
 RPGの本来あるべき姿なのかなと思いました。
 (堀井雄二のこだわり!?)

 3Dのぐりぐりな動きには、2時間くらいのプレイで慣れると思います。
 また洞窟で方向が分からなくなって迷うのも楽しみ方の一つかなと…(笑)

 [今後のドラクエについて]
 次回作もそうですが、今回の3Dエンジンを使ったリニューアルも期待します!!

(2)リンク
ドラゴンクエストVIII 空と海と大地と呪われし姫君

ドラゴンクエストVIII 空と海と大地と呪われし姫君

  • 出版社/メーカー: スクウェア・エニックス
  • メディア: Video Game

[Game's Review]ファミコンミニ スーパーマリオブラザーズ

(1)レビュー
 旧ファミコン時代が懐かしく思い、つい買ってしまいました。
 当時のゲームは、シンプルが故に奥の深いゲームが多く、
 「スーパーマリオ」もその一つだと思います。

 【良い点】
 ・FC版と同様の操作性です。
 ・裏技もほぼ移植。
  以下、再現させた裏技。
  ・コンティニュー(タイトルからAボタン+スタート)
  ・スケートマリオ
   (ファイヤマリオで、土管から出た直前にAとBを同時押しっぱなし)
  ・マイナス1面(ステージ1-2)
  ・無限増殖
  ・透明パックンフラワー(8-4の水中面)
 【イマイチな点】
  ・9-1以降のステージがプレイできない。
   (FC版は「テニス」との併せ技が必要な為、GB、DSでは無理だと思いますが…)
  ・カメをハンマーブロスに当てようとすると、なぜかすり抜ける。(ステージ8-3)
   FC版では必ずヒットしていたはず。。。

(2)リンク
ファミコンミニ スーパーマリオブラザーズ

ファミコンミニ スーパーマリオブラザーズ

  • 出版社/メーカー: 任天堂
  • メディア: Video Game


2009年4月26日日曜日

[雑記]黄色い新幹線

出張の帰り広島駅にて偶然見かけました。
この黄色い新幹線は『ドクターイエロー』とも呼ばれ、
偶然見かけるとその日は、いいことがあるそうです。

偶然見かけたのはこれで2回目です。

前回は通り過ぎるのを遠めでしか見れませんでしたが、
今回は回送電車だったので写真を撮る余裕がありました。
その分、いいことあるといいなぁ。。。

ドクターイエロー(その1)
ドクターイエロー(その1)
ドクターイエロー(その2)
ドクターイエロー(その2)

2009年4月20日月曜日

[雑記]Excelで『履歴』は予約語?


Microsoftの表計算ソフト『Excel』のトリビア的ネタです(笑)

『履歴』という名前でシートを作成しようとすると、
こんなエラーが出ます。
『履歴』は予約語?

『履歴』が予約語!?Σ(゚□゚;)

予約語は半角英数字が一般的だと思っていたので、
全角が予約語になるのは珍しいですね。

ひょっとして、Excelを英語から日本語に翻訳する際に、
予約語も一緒に翻訳しちゃったのかな?

試しに『history』でシートを作ろうとすると、

普通にシートが作れます。。。

特にエラーも無く普通に作れちゃいました。。。

『履歴』ってどんな予約語なんだろう。。。

2009年4月12日日曜日

[.NET]例外の再スロー(Throwの引数の有無)

[はじめに]
・.NET系言語(C#、VB.NET)のプログラムコードで、
 以下のような構文を見かけることがあります。
  Try 
    Dim x As Integer = func2(a) 
    Return x 
  Catch ex As Exception 
    '何らかの例外後の後処理をして、再スロー 
    '(例外後の処理は割愛)... 
    Throw ex    '←ここに注目 
  End Try
[VB.NET]例外の再スロー[Throwの引数がある場合]
 Tryステートメント内で発生した例外をCatchして、
 再度スローする処理で、「Throw ex」と書く人が結構多いようですが、
 実はこのような書き方をすると、
 ここでCatchする以前のトレース情報が失われてしまうのです。

 トレース情報を保持しつつ再スローするには、
 以下の様に、「Throw ex」ではなく「Throw 」と記述します。
  Try 
      Dim x As Integer = func2(a) 
      Return x 
  Catch ex As Exception 
      '何らかの例外後の後処理をして、再スロー 
      '(例外後の処理は割愛)... 
      Throw    '←exは省略します。 
  End Try 
[VB.NET]例外の再スロー[Throwの引数がない場合]

 なぜか書籍やMSDNにも、前者の書き方でサンプルを紹介している為、
 知らない人が多いようです。
 (Throwステートメントとは直接関係ないサンプルだから、
  あまり重要視していないのだと思いますが…)
[参考文献]
「C#クックブック 第3版」
 「レシピ4.1 キャッチした例外を再スローするタイミングを把握する」で、
 Throwステートメントの引数の有無の違いを明確に説明しています。
 「Throw」(引数なし)の記述を推奨しています。
「プログラミングC#―C#2.0/.NET2.0/Visual Studio2005対応」
 「11.4 例外の再スロー」で、
 理由の説明はないが、「Throw」(引数なし)の記述を推奨しています。
[検証]  Throwステートメントの仕様について、  2つのパターンの検証プログラムを実行して、結果を比較してみた。
パターン1
 Throwステートメントに引数がある場合、
 Button1_Click()→Method1()→Method2()→Method3()→Method4()と
 メソッドを呼び、最下層のMethod4()で
 ゼロ除算の例外(System.DevideByZeroException)を意図的に発生させる。
 各々のメソッドのCatch句では、「Throw ex」(引数あり)で例外を再Throwする。
 最上位メソッドにて、例外の内容(ToString()した結果)を表示する。
パターン2
 Throwステートメントに引数がない場合、
 Button1_Click()→Method1()→Method2()→Method3()→Method4()と
 メソッドを呼び、最下層のMethod4()で
 ゼロ除算の例外(System.DevideByZeroException)を意図的に発生させる。
 各々のメソッドのCatch句では、「Throw 」(引数なし)で例外を再Throwする。
 最上位メソッドにて、例外の内容(ToString()した結果)を表示する。
・パターン1(Throwステートメントに引数がある場合)
Private Sub Button1_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    Dim num As Integer

    Try
        num = Method1(1, 0)
    Catch ex As Exception
        MessageBox.Show( _
            ex.ToString(), _
            "例外[Throwの引数がある場合]")
    End Try
End Sub

Private Function Method1( _
    ByVal a As Integer, _
    ByVal b As IntegerAs Integer

    Try
        Return Method2(a, b)
    Catch ex As Exception
        Throw ex
    End Try
End Function

Private Function Method2( _
    ByVal a As Integer, _
    ByVal b As IntegerAs Integer

    Try
        Return Method3(a, b)
    Catch ex As Exception
        Throw ex
    End Try
End Function

Private Function Method3( _
    ByVal a As Integer, _
    ByVal b As IntegerAs Integer

    Try
        Return Method4(a, b)
    Catch ex As Exception
        Throw ex
    End Try
End Function

Private Function Method4( _
    ByVal a As Integer, _
    ByVal b As IntegerAs Integer

    Try
        'b=0の時に例外が発生する。
        Return a \ b
    Catch ex As Exception
        Throw ex
    End Try
End Function
[VB.NET]例外[Throwの引数がある場合]
・パターン1の実行結果(Throwステートメント[引数あり])  Throwの引数を指定した場合は、  保持されているトレース情報は、Method1、Button1_Clickのみで、  Method2、Method3、Method4は保持されていないことがわかります。  引数指定での再スローでは、それより前のトレース情報を保持しない為です。  この例では、   Method3で再スローする時に、Method4以降のトレース情報を保持しない、   Method2で再スローする時に、Method3以降のトレース情報を保持しない、   Method1で再スローする時に、Method2以降のトレース情報を保持しない為、  図のような結果になります。 例外[Throwの引数がある場合] ・パターン2(Throwステートメント[引数なし])
Private Sub Button1_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    Dim num As Integer

    Try
        num = Method1(1, 0)
    Catch ex As Exception
        MessageBox.Show( _
            ex.ToString(), _
            "例外[Throwの引数がない場合]")
    End Try
End Sub

Private Function Method1( _
    ByVal a As Integer, _
    ByVal b As IntegerAs Integer

    Try
        Return Method2(a, b)
    Catch ex As Exception
        Throw
    End Try
End Function

Private Function Method2( _
    ByVal a As Integer, _
    ByVal b As IntegerAs Integer

    Try
        Return Method3(a, b)
    Catch ex As Exception
        Throw
    End Try
End Function

Private Function Method3( _
    ByVal a As Integer, _
    ByVal b As IntegerAs Integer

    Try
        Return Method4(a, b)
    Catch ex As Exception
        Throw
    End Try
End Function

Private Function Method4( _
    ByVal a As Integer, _
    ByVal b As IntegerAs Integer

    Try
        'b=0の時に例外が発生する。
        Return a \ b
    Catch ex As Exception
        Throw
    End Try
End Function
[VB.NET]例外[Throwの引数がない場合]
・パターン2の実行結果(Throwステートメント[引数なし])  Throwの引数を指定しない場合は、  関連するトレース情報(Method1、Method2、Method3、Method4、Button1_Click)を  全て保持していることがわかります。 例外[Throwの引数がない場合]

[VBA]ExcelVBAでオブジェクト指向の継承

[はじめに]
・ExcelのVBA(Visual Basic for Application)は、
 完全オブジェクト指向言語(JavaやC#等)ほどではないですが、
 オブジェクト指向によるプログラミングをサポートしています。
 『オブジェクト指向』と言えば、
 代表的な性質として以下の3つのキーワードがあります。
代表的な性質
継承
2つのクラス間で親子関係を持ち、子クラスが親クラスの性質を受け継ぐこと。
カプセル化
オブジェクト内部のデータを隠蔽したり(データ隠蔽)、オブジェクトの振る舞いを隠蔽したり、
オブジェクトの実際の型を隠蔽したりすることをいう。
多態性(ポリモフィズム)
実行される処理の実体が、コールされたメッセージではなく、メッセージを受けたオブジェクトに
よって決定される性質。
また、この性質を使って、
「同一のメッセージを使って、オブジェクトごとに異なった処理を行わせること」
[VBAのオブジェクト指向]
 VBAのオブジェクト指向は、完全オブジェクト指向言語(JavaやC#等)のそれと比べると、
 『子クラスのメソッドを経由して親クラスの変数やメソッドにアクセスできない』、
 『子クラス内から親クラスの変数やメソッドにアクセスできない』等の制限事項がある。
[多態性(ポリモフィズム)]
 『多態性(ポリモフィズム)』の説明で、
 『動物』に『鳴く』メッセージを通知する例がよく挙げられる。
 以下に、『多態性(ポリモフィズム)』を利用したサンプルコードを示す。
[クラス図]
クラス図
[クラスの説明]
Mammalクラス
 哺乳類を表すクラス。
 メソッドとして、Cry()を実装。
Dogクラス、Catクラス、Crowクラス
 イヌ、ネコ、カラスを表すクラス。各々のクラスはMammal(哺乳類)クラスを継承。
 メソッドとして、Mammal_Cry()を実装。
 ([親クラス名]_[親クラスのメソッド名]で、親クラスのメソッドをオーバーライドできます。)
[多態性(ポリモフィズム)]
・Dogオブジェクト、Catオブジェクト、Crowオブジェクトを
 Mammalオブジェクトの配列に格納する。
 MammalオブジェクトのCrowメソッドを経由して、
 Dogオブジェクト、Catオブジェクト、CrowオブジェクトのCrowメソッドを呼ぶ。
 以下のサンプルでは、3つのMammalオブジェクトのCryメソッドを呼んでいるが、
 実際に実行されるのは、Dog、Cat、CrowのMammal_Cryメソッドであることを示している。
 同一のCryというメッセージをMammalオブジェクトに通知しているが、
 受け取った各々のオブジェクト毎に異なった動作をしていることになる。(多態性(ポリモフィズム))
[サンプルコード]
Option Explicit
'[クラス名] Mammalクラス
'[説明] 哺乳類を表すクラス
'       Dog(イヌ)、Cat(ネコ)、Crow(カラス)の
'       親クラスとして利用

'[メソッド名]
'   Cry
'[機能]
'   動物の鳴き声を取得します。
'[前提条件]
'   子クラスでオーバーライドして下さい。
Function Cry() As String
    Err.Raise _
        999, , _
        "このクラスのメソッドは直接呼ぶことはできません。" & vbCrLf & _
        "子クラスでオーバーライドして呼んで下さい。" 
End Function
[ExcelVBA]Mammalクラス


Option Explicit
'[クラス名] Dogクラス
'[説明] イヌを表すクラス

'Mammalクラスを実装
Implements Mammal

'[メソッド名]
'   Mammal_Cry
'[機能]
'   動物の鳴き声を取得します。
'[備考]
'   メソッド名は、「親クラス名」_「メソッド名」
Public Function Mammal_Cry() As String
    Mammal_Cry = "ワンワン"
End Function
[ExcelVBA]Dogクラス


Option Explicit
'[クラス名] Catクラス
'[説明] ネコを表すクラス

'Mammalクラスを実装
Implements Mammal

'[メソッド名]
'   Mammal_Cry
'[機能]
'   動物の鳴き声を取得します。
'[備考]
'   メソッド名は、「親クラス名」_「メソッド名」
Public Function Mammal_Cry() As String
    Mammal_Cry = "ニャー"
End Function
[ExcelVBA]Catクラス


Option Explicit
'[クラス名] Crowクラス
'[説明] カラスを表すクラス

'Mammalクラスを実装
Implements Mammal

'[メソッド名]
'   Mammal_Cry
'[機能]
'   動物の鳴き声を取得します。
'[備考]
'   メソッド名は、「親クラス名」_「メソッド名」
Public Function Mammal_Cry() As String
    Mammal_Cry = "カァーカァー"
End Function
[ExcelVBA]Crowクラス


Private Sub CommandButton1_Click()

    '哺乳類のオブジェクト変数を宣言
    '要素数3つの配列を用意
    Dim man(2) As Mammal
    
    'イヌ、ネコ、カラスの
    'オブジェクトを生成
    Set man(0) = New Dog
    Set man(1) = New Cat
    Set man(2) = New Crow
    
    '各々の動物の鳴き声を表示
    MsgBox man(0).Cry()
    MsgBox man(1).Cry()
    MsgBox man(2).Cry()

    'オブジェクトを解放
    Set man(0) = Nothing
    Set man(1) = Nothing
    Set man(2) = Nothing

End Sub
[ExcelVBA]呼び出し元


[実行結果]
多態性(ポリモフィズム)の実行結果

2009年1月11日日曜日

[.NET]カスタマイズした構成情報の利用(.NET1.1以前が対象)

[はじめに]
(1)カスタム構成セクションとは?
  通常、アプリケーションの構成情報は、appSettingsノード配下の
  addノード(key属性とvalue属性)に記述するルールですが、
  独自のルール(独自のXMLタグ)で定義することもできます。
  この独自のXMLタグで定義された構成情報を、「カスタム構成セクション」と呼びます。
  「カスタム構成セクション」にアクセスする為には、
  プログラム上で「カスタム構成セクションハンドラ」クラスを実装し、
  構成ファイルに「カスタム構成セクションハンドラ」を追加する必要があります。
(2)カスタム構成セクションハンドラとは?
  カスタム構成セクションにアクセスする為には、
  その独自のXMLタグを解析する必要があります。
  その独自のXMLタグを解析するクラスを、「カスタム構成セクションハンドラ」と呼びます。
  カスタム構成セクションハンドラは、以下の(a)(b)の条件に従って実装する必要があります。
   (a)System.Configuration.IConfigurationSectionHandlerインタフェースを実装する。
   (b)IConfigurationSectionHandlerインタフェースのCreateメソッドに、
     カスタム構成セクションを解析する処理を実装する。
(3)カスタム構成セクションハンドラが、カスタム構成セクションにアクセスするには?
  カスタム構成セクションハンドラがカスタムセクションにアクセスする為には、
  構成ファイルに、構成セクションハンドラを追加する必要があります。
  追加することにより、カスタム構成セクションハンドラとカスタムセクションの対応付けを
  定義したことになります。
(4)利用可能な.NET Frameworkのバージョンは?
  本記事のサンプルは、.NET1.1以前で主流だった方法です。
  .NET2.0以降では、「ConfigurationSection」クラスを使用する方法が
  推奨されています。(.NET2.0以降でも使用可能)
(5))参考文献
  ・『MSDN Library for VisualStudio2008日本語版』
  ・『MCTSスキルチェック問題集70-536 .NET Framework2.0アプリケーション構築基礎』

カスタム構成セクションにアクセスする例を、以下の(1)~(4)に分けて示します。

(1)カスタム構成セクションの定義
  例として、日本の地域と県、県と県庁所在地の対応を定義しています。
[ソース]
<configuration>
  <myCustomGroup>
    <Country Name="Japan">
      <Area Name="Kanto">
        <Prefecture Name="Tokyo" MajorCity="Tokyo"/>
        <Prefecture Name="Kanagawa" MajorCity="Yokohama"/>
        <Prefecture Name="Ibaragi" MajorCity="Mito"/>
      </Area>
      <Area Name="Chubu">
        <Prefecture Name="Aichi" MajorCity="Nagoya"/>
        <Prefecture Name="Gifu" MajorCity="Gifu"/>
        <Prefecture Name="Mie" MajorCity="Tsu"/>
      </Area>
    </Country>
  </myCustomGroup>
        (以下省略)
          :
例:カスタム構成セクションの定義

(2)カスタム構成セクションハンドラの実装   System.Configuration.IConfigurationSectionHandlerインタフェースを   実装したクラスを定義します。   System.Configuration.IConfigurationSectionHandlerインタフェースの   Createメソッドに、カスタム構成セクションのアクセス処理を実装します。   この例では、カスタム構成セクションから、県と県庁所在地の一覧を取得し、   HashTableに格納しています。 [ソース]
''' <summary>
''' カスタム構成セクションハンドラ
''' ※.NET1.1以前で使用可能。
'''  .NET2.0以降ではSystem.Configuration.ConfigurationSectionクラスを推奨
''' </summary>
''' <remarks></remarks>
Public Class MyCustomConfigHandler1_1
    Implements System.Configuration.IConfigurationSectionHandler

    ''' <summary>
    ''' 構成セクションハンドラを作成する。
    ''' </summary>
    ''' <param name="parent">親オブジェクト</param>
    ''' <param name="configContext">構成コンテキストオブジェクト</param>
    ''' <param name="section">セクションXMLノード</param>
    ''' <returns>作成されたセクションハンドラオブジェクト</returns>
    ''' <remarks></remarks>
    Public Function Create( _
        ByVal parent As Object, _
        ByVal configContext As Object, _
        ByVal section As System.Xml.XmlNode) As Object _
        Implements _
        System.Configuration.IConfigurationSectionHandler.Create

        Dim configTable As New Hashtable()

        For Each areaNode As XmlNode In section.ChildNodes
            For Each prefNode As XmlNode In areaNode.ChildNodes
                configTable.Add( _
                    prefNode.Attributes("Name").Value, _
                    prefNode.Attributes("MajorCity").Value)
            Next
        Next

        Return configTable

    End Function
End Class
[VB.NET]例:カスタム構成セクションハンドラの実装

(3)構成ファイルにカスタム構成セクションハンドラの追加   「myCustomGroup」、「Country」の対応付けを定義し、   更に「Country」のセクションハンドラを定義しています。   type属性には、カスタム構成セクションハンドラのアセンブリ修飾名を指定します。   アセンブリ修飾名については、   MessageBox.Show( _    New MyCustomConfigHandler1_1().GetType().AssemblyQualifiedName)   で確認できます。 [ソース]
<configuration>
  <configSections>
    <sectionGroup name="myCustomGroup" >
      <section 
        name="Country" 
        type="CustomConfig.MyCustomConfigHandler1_1, 
              CustomConfig, 
              Version=1.0.0.0, 
              Culture=neutral, 
              PublicKeyToken=null"/>
    </sectionGroup>
  </configSections>
        (以下省略)
          :
例:カスタム構成セクションハンドラの追加

(4)構成情報の取得   以下に、カスタム構成セクションハンドラを使用して構成情報を取得する例を示します。   取得には、System.Configuration.ConfigurationSettingsクラスの   GetConfigメソッドを使用します。(※.NET2.0以降では警告がでます。)   GetConfigの引数には、起点となるカスタム構成セクションのノード名を指定します。 [ソース]
Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles Button1.Click

    Dim rtn As Object = Nothing
    Dim configTable As Hashtable = Nothing

    '「myCustomGroup/Country」のXMLノードを起点とし、
    '構成情報を取得する。
    rtn = System.Configuration.ConfigurationSettings.GetConfig( _
        "myCustomGroup/Country")
    configTable = CType(rtn, Hashtable)

    '取得した構成情報をメッセージボックスに表示
    Dim sb As New StringBuilder()
    For Each k As String In configTable.Keys
        sb.Append(k & ":" & configTable(k).ToString() & vbCrLf)
    Next
    MessageBox.Show(sb.ToString())

End Sub
[VB.NET]例:カスタム構成セクションハンドラを使用して構成情報を取得する

2009年1月1日木曜日

[Algo]組合せの数(nCm)の算出

[はじめに]
・n個の中からm個を選ぶ組合せの数(nm)を算出するプログラムです。
 例:a、b、cの3個の中から2個を選ぶ組合せは、
   ab、ac、bcの3通りであり、その数を数学的表記で『32』と表現します。
 .NETのクラスライブラリには算出するメソッドがないようなので作ってみました。
nmを算出する公式はいくつかありますが、
 代表的な公式と各々の特徴について、以下にまとめます。
・参考文献
 『Javaによるはじめてのアルゴリズム入門』

以下に、算出方法に対するプログラム例を示します。

(1)階乗による算出
 公式nm=n!/{m!×(n-m)!}
/// <summary>
/// 異なるn個のものからm個を選ぶ
/// 組み合わせの総数 nCmを取得する。
/// </summary>
/// <param name="n">n</param>
/// <param name="m">m</param>
/// <returns>nCm</returns>
public static decimal CalcComb01(decimal n, decimal m)
{
    //nCm = nCm-1 ×(n-m+1)/ m 
    return CalcFact(n) / (CalcFact(m) * CalcFact(n - m));
}

/// <summary>
/// 階乗を計算する。
/// </summary>
/// <param name="n">n</param>
/// <returns>nの階乗(n!)</returns>
public static decimal CalcFact(decimal n)
{
    if (n <= 0m) {
        return 1m;
    }
        
    return n * CalcFact(n - 1);
}
[C#][階乗による算出]
異なるn個のものからm個を選ぶ組み合わせの総数nmを取得する。

(2)漸化式による算出
 一般的に、漸化式の計算は再帰処理で実装できます。
 公式
 (i)m=0の場合
  nm=1
 (ii)m>0の場合
  nmnm-1×(n-m+1)/m
/// <summary>
/// 異なるn個のものからm個を選ぶ
/// 組み合わせの総数 nCmを取得する。
/// </summary>
/// <param name="n">n</param>
/// <param name="m">m</param>
/// <returns>nCm</returns>
public static decimal CalcComb02(decimal n, decimal m)
{
    //以下の漸化式に従って、再帰により算出する。

    //(1)m=0の場合、
    //      nCm = 1
    if (m == 0)
    {
        return 1;
    }

    //(2)m≠0の場合、
    //      nCm = nCm-1 ×(n-m+1)/ m 
    return CalcComb02(n, m - 1) * (n - m + 1) / m;

}
[C#][漸化式による算出]
異なるn個のものからm個を選ぶ組み合わせの総数nmを取得する。

(3)Π(パイ)による算出
 「(2)漸化式による算出」の公式は、
 総乗(掛け算を集約したもの)と解釈できるので、
 以下の公式でも表現できます。
 公式nm=Π{(n-k+1)/k} (※1≦k≦M)
/// <summary>
/// 異なるn個のものからm個を選ぶ
/// 組み合わせの総数 nCmを取得する。
/// </summary>
/// <param name="n">n</param>
/// <param name="m">m</param>
/// <returns>nCm</returns>
public static decimal CalcComb03(decimal n, decimal m)
{
    //組合せ(nCm)を、
    //以下の公式に従って、ループにより算出する。
    //         m
    // nCm = Π {(n-k+1)/ k }
    //         k=1

    decimal product = 1;

    for(decimal k = 1 ; k <= m ; k++)
    {
        product = product * (n - k + 1) / k;
    }

    return product;

}
[C#][Π(パイ)による算出]
異なるn個のものからm個を選ぶ組み合わせの総数nmを取得する。

[雑記]ドローン(DJI Mini 3)

(1)雑記 もともと多趣味の友人 masakazu Drone 氏が、 最近、 ドローン にハマり始めて、 更に、新たな趣味が増えたとのこと。 ドローン を始めてから、 まだ1年も経っていないとのことですが、 旅行先で山や川の景色を 空撮 して、 Youtube ...