フレームワークの参照が難しすぎ

mac os用のソフトウェアを作成するためにxcodeを使ってプログラミングをしようとしていたのだけれど、いつも通りプログラミングを始める前の環境構築に苦労した。既存のフレームワークを使うことで手早くソフトを開発しようと都合のいいことを考えていたら、フレームワークの参照の設定の仕方からわからない体たらく。さらにフレームワークを設定する前にそのフレームワークを自分で作成しなければならないことがわかって、さらにその前の準備としてsubversionというソフトウェアをインストールしないといけなくて、そのsubersionというのはどうやってインストールするのかというのを調べて・・・

プログラムを組まないで半日潰れた。でもまあ、なんとなく仕組みはわかってきたので無駄骨ということにはならなかった。

mschartが表示されない

vb.netで作成したwindowsアプリケーションにグラフを表示させてみようと思って、mschartというグラフ描画コンポーネントを使うことにした。そして、実装が終わってリリースしたものを他のマシンで動作確認しようとしたら、問題が発生したためアプリケーションを終了しますということになった。エラーの原因は、mschartを動かすためのvb6ランタイムがインストールされていないことがどうもそれらしい。vb6のランライムがインストールされていれば、mschartを表示することができる。今私が作成しようとしているのはvb.net用のアプリケーションなので、動かすためには.net frameworkをインストールする必要があるけれど、それにさらにvb6のランタイムが無いと動かないアプリケーションというのはダサすぎて作りたくない。というわけで、mschartを使うのはやめて別のコンポーネントを使ってグラフを表現することにしてみる。

select文で特定のセルに文字列を挿入する

sqlのselect文で列の値へテーブルの値ではなくて、特定の文字列を挿入した場合のsql文。たとえばテーブルの合計を出したい場合などのとき、1列目のセルの値は文字列で’合計’、2列目のセルの値はsum関数で取得した合計値を入れる・・・というようなレアなケース。

サンプルコード

SELECT ‘合計’,SUM(列1) FROM テーブル1

というような具合。簡単過ぎてググっても見つからなかったので覚え書き。

データグリッドの列の並び順が変わってしまう

datagridviewへdatasetにセットされたテーブルをバインドしたとき、一度目のバインドでは思い通りの列の並び順にならぶ。次に、同じデータグリッドへ列数が少ないテーブルをバインドする。これも思い通りの列の並び順で表示される。そして次に、一度目と同じテーブルをセットしたら、2度目の並び順を引き摺ったまま表示されてしまい、思い通りの並び順になってくれない。

またこれもvisual studioのわけのわからないバグなのだろうか。とりあえずググって調べてみたら、データグリッドの列の表示順を設定することができるプロパティがあることがわかったのでそれで対処することにした。

サンプルコード

        me.datagridview1.Columns(0).DisplayIndex = 0
        me.datagridview1.Columns(1).DisplayIndex = 1
        me.datagridview1.Columns(2).DisplayIndex = 2
        me.datagridview1.Columns(3).DisplayIndex = 3
        me.datagridview1.Columns(4).DisplayIndex = 4
        me.datagridview1.Columns(5).DisplayIndex = 5

参考サイト

DataGridViewの列の並びがビルド時に変わるのを防ぎたい

visual studio 2005 が不具合を起こした

デバッグ作業中にブレークポイントを設定してからデバッグを開始したら、ブレークポイントのマークが赤い丸じゃなくて黄色で?マークが付いたものにいきなり変わった。なんぞこれ?とは思ったけど、特に気にせずにデバッグ作業をやってみるとブレークポイントに引っかからない。その?マークがついた黄色い丸のブレークポイントの変わりに現れたものにマウスカーソルをのっけてみると、

ブレークポイントは現在の設定ではヒットしません。ソースコードが元のバージョンと異なります。

という風に怒られる。いきなりそんなこと言われても全然思い当たる節がない。とはいってもデバッグできないと困るのでエラー内容に書いてある解決方法の、ツールのオプションからデバッグを選択して、その全般の”元のバージョンと完全に一致するソースファイルを必要とする”のチェックをはずすということを設定した。これで、ブレークポイントで止まるようになった。が、しかし、デバッグの止まり方がおかしい・・・。ステップインで一行ずつ処理を追いかけてみると、if文の分岐でその中身を全部通過している。っていうか分岐していない。そういえばいつものvisual studioのエディタの見た目もなんかおかしい。(ブロックの始まりの一文がなんか背景がグレーっぽい色になってるし)

と、色々焦りまくって試行錯誤した結果私が発見した強引な対処法。

  1. デバッグでステップインの進行が怪しい関数をひとまず切り取る。
  2. すると、コンソールにエラーがズラーっと表示される。宣言がされてないとかメンバーじゃないとかめちゃくちゃ怒られる。
  3. めいいっぱい怒られた後で、切り取った関数をもとにあった場所へ貼り付ける。

このようなことをやってみたら、私の環境では直りました。同じような現象になっている人はやってみると直るかもしれません。

西暦の日付を和暦の日付に変換してみる

2008/03/15

というような西暦の日付を、

平成20年3月15日(土)

といような形式でデータが欲しいので挑戦してみた。他のサイトを見てみるとformat関数で西暦から和暦に変換というのが検索エンジンで沢山でてきたので簡単にできるだろうとタカをくくっていたら、いや、できないんだけど・・・。Format(Now,”gggyy年MM月”)で一発変換というようなことをどこのサイトを見ても書いているので真似してやってみたら西暦08年とかわけのわからない数字を返してくれてどっと疲れた。仕方がないので地道に変換をしてみることにする。

とりあえず手がかりとして見つかったのはJapaneseCalendarクラスgetEraメソッド(ゲッテラメソッド)を使うと元号のようなものを取得できるらしいとのこと。System.Globalization.JapaneseCalendar をimportsすると使えるようになる模様。2008を平成20年という形式でデータが欲しいため、下記のgetGengoYear関数を作成してみた。date型のパラメータを渡して呼ぶと文字列型の元号プラス年で返してくれる。

元号を返してくれる関数:getGengoYear関数

    Private Function getGengoYear(ByVal targetDate As Date) As String

        'これに元号を入れる
        Dim gengo As String

        'これに和暦の年を入れる
        Dim targetGengoYear As String

        'JapaneseCalendarクラスのインスタンス化
        Dim jpCal As Globalization.JapaneseCalendar = New Globalization.JapaneseCalendar

        'パラメータの日付から元号を判断する
        Select Case jpCal.GetEra(targetDate)
            Case 1
                gengo = "明治"
            Case 2
                gengo = "大正"
            Case 3
                gengo = "昭和"
            Case Else
                gengo = "平成"
        End Select

        '元号と和暦の年とをくっつける
        targetGengoYear = gengo & jpCal.GetYear(targetDate) & "年"

        '出来上がった元号プラス和暦年を返す
        Return targetGengoYear

    End Function

これで難関の元号を取得することができた。次は3月15日(土)の部分。さっき作ったgetGengoYear関数と組み合わせて下記のようなgetJapaneseDate関数というものを作ってみた。date型のパラメータを渡してあげると、平成20年3月15日(土)という形式で返してくれる。

和暦を返してくれる関数:getJapaneseDate関数

    private Function getJapaneseDate(ByVal targetDate As Date) As String

        'これに和暦を入れる
        Dim japaneseDate As String

        'これに元号を格納する
        Dim targetYear As String = getGengoYear(targetDate)

        '曜日の条件分岐。
        If targetDate.DayOfWeek = DayOfWeek.Monday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(月)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Tuesday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(火)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Wednesday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(水)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Thursday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(木)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Friday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(金)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Saturday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(土)"

        Else

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(日)"

        End If

        '出来上がった和暦を返す
        Return japaneseDate

    End Function

サンプルコード

実際に使うときは下記のような感じになる・・・かな。

Imports System.Globalization.JapaneseCalendar

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim todayDate As Date = Today.Date
        MsgBox(getJapaneseDate(todayDate))

    End Sub

    private Function getJapaneseDate(ByVal targetDate As Date) As String

        'これに和暦を入れる
        Dim japaneseDate As String

        'これに元号を格納する
        Dim targetYear As String = getGengoYear(targetDate)

        '曜日の条件分岐。
        If targetDate.DayOfWeek = DayOfWeek.Monday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(月)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Tuesday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(火)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Wednesday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(水)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Thursday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(木)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Friday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(金)"

        ElseIf targetDate.DayOfWeek = DayOfWeek.Saturday Then

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(土)"

        Else

            japaneseDate = targetYear & Format(targetDate, "MM月dd日") & "(日)"

        End If

        '出来上がった和暦を返す
        Return japaneseDate

    End Function

    Private Function getGengoYear(ByVal targetDate As Date) As String

        'これに元号を入れる
        Dim gengo As String

        'これに和暦の年を入れる
        Dim targetGengoYear As String

        'JapaneseCalendarクラスのインスタンス化
        Dim jpCal As Globalization.JapaneseCalendar = New Globalization.JapaneseCalendar

        'パラメータの日付から元号を判断する
        Select Case jpCal.GetEra(targetDate)
            Case 1
                gengo = "明治"
            Case 2
                gengo = "大正"
            Case 3
                gengo = "昭和"
            Case Else
                gengo = "平成"
        End Select

        '元号と和暦の年とをくっつける
        targetGengoYear = gengo & jpCal.GetYear(targetDate) & "年"

        '出来上がった元号プラス和暦年を返す
        Return targetGengoYear

    End Function

End Class

datagridの列幅の調整ができない

こんなことで嵌るのは私くらいかもしれないけれど一応備忘録

datagridviewのプロパティにある、AllowUserToResizeColumnsの値をtrueに設定しても、実際にデータをバインドしてみたら列幅の調整が効かない場合の原因。原因は、AutoSizeColumnsModeの値でAllCellsを設定していたために調整することが出来なかった模様。まあ、いわゆる機能が競合していたというか、AutoSizeColumnsModeの方が優先されていたためということかな。値はnoneに設定して、コードでcolumnのwidthを設定することに変更した。

謎のエラーが発生した・・・

‘System.InvalidOperationException’ の初回例外が System.Data.dll で発生しました。
‘System.Data.OleDb.OleDbException’の初回例外が system.data.dllで発生しました。

プログラムをリファクタリングしていたら起動時にコンソールへ上記のエラーが表示されるようになった。思い当たる節がないんだが・・・。sqlのinsert文を手直ししたけれど、起動時に引っかかる箇所じゃないし、DBのテーブルにフィールドを一個追加したことはしたけれど、起動時に見るテーブルとは無関係だし・・・。謎。

バックアップを作業前に念のためとっていたため、どこが引っかかるか再現させてみようとしたら、今度は現れない・・・。謎。

(その後)
データベースのテーブルのフィールド名を追加したり、名前を変えたりしたら、
‘System.Data.OleDb.OleDbException’の初回例外が system.data.dllで発生しました。
というエラーがまた出た。一度visual studioを終了して、プロジェクトを開きなおしたら出なくなった。またしても謎。推測だけれど、デバッグでDB接続関連のエラーが一度出たらその後もずっとで続けるのだろうか。それとも私のvisualstudioが壊れてるか。

メモ2

構文の備忘録。下記のコードは拙作のシンプルな家計簿(仮)で使っているコードです。あくまでサンプルです。

if文

if文のコードサンプル。下記のコードは時間によって挨拶文を変化させる分岐。

        '現在の時間を取得
        Dim nowHour As integer = DateTime.Now.Hour

        '現在時刻が5時から11時の間ならば、
        If (nowHour > 4) And (nowHour < 12) Then

                'ユーザ名+おはよう
                Me.hello_label.Text = title_user & "さん おはよう!"

        '現在時刻が12時から17時の間ならば、
        ElseIf (nowHour >= 12) And (nowHour < 18) Then

                'ユーザ名+こんにちは
                Me.hello_label.Text = title_user & "さん こんにちは!"

        '上記以外の場合は、
        Else

                'ユーザ名+こんばんは
                Me.hello_label.Text = title_user & "さん こんばんは!"

        End If

for文

for文のコードサンプル。下記のコードはデータグリッド内の数値がプラスかマイナスかを一行ずつ判断例。

        'データグリッドの行数を取得
        ds_record = main_form.dg_search.Rows.Count

        'データグリッドの行数分ループ
        For i = 0 To (ds_record - 1)

            'データグリッド内の金額を取得。
            cb_item = Convert.ToDecimal(main_form.dg_search.Rows(i).Cells(4).Value)

            '金額が0以下(マイナス)ならば、
            If cb_item < 0 Then

                '金額のセルのカラーを赤色に設定
                main_form.dg_search.Rows(i).Cells(4).Style.ForeColor = Color.Red

            '金額が0以下以外ならば、
            Else

                '金額のセルのカラーを緑色に設定
                main_form.dg_search.Rows(i).Cells(4).Style.ForeColor = Color.Green

            End If

        '次の行へ
        Next i

select case 文

日付の値によって元号を分岐させるselect~case文のサンプル


        Select Case jpCal.GetEra(targetDate)

            Case 1
                gengo = "明治"

            Case 2
                gengo = "大正"

            Case 3
                gengo = "昭和"

            Case Else
                gengo = "平成"

        End Select

menustripのショートカットキーが効かない

また嵌ってしまったので備忘録。vb.netのmenustripコントロールに配置されたアイテムにshortcutkeysプロパティでキーを割り当てても、ショートカットが機能しない現象について。shortcutkeysプロパティでは色々と複雑なキーを割り当てることができるようになっているけれど、menustripの項目に設置しても何の反応もない・・・。あのファイル(F)や編集(E)や表示(V)といったお決まりの項目。ショートカットキーを設定して、設定したショートカットキーを押したときにはmenustripの項目がプルダウンするというか、メソッドとしてはshow()の動作をしてもらいたいのだけれど、効かない。なんでだ?としばらく考え込んでみたところ、menustripの項目にショートカットを割り当てるには&(アンパサンド)使わなければならない模様。テキストプロパティに、例えばファイルのメニュー項目ならば”ファイル(&F)”という風に入力すると、altキー+Fキーでプルダウンするようになる。こんな単純なことだとは知らずに、危うくkeypressイベントでkeycharを拾ってshowメソッドを呼ぶしかないかと実行するところだった。

・・・で、なんでshortcutkeysプロパティが効かないんだろう?