進捗状況を表示するプログレスバー

プログレスバーの使い方

プログレスバーは、アプリケーションが何かの処理中であることをユーザに知らせてあげるという役割を持っている。時間がかかる処理などの場合にその進行状況をプログレスバーのアニメーションで明示することで、ユーザに安心感を与えることができる・・・かもしれない。

自分なりにプログレスバーの使い方を調べてみたところ、どうやらプログレスバーはプロパティの初期値と最大値、増加率を設定し、増加するタイミングにメソッドを呼び出すことで進捗率を表現する模様。具体的なプロパティ名は下記の通り。

        'プログレスバーの初期値
        Me.progressBar.Value = 0

        'プログレスバーの最大値
        Me.progressBar.Maximum = 100

        'プログレスバーの増加率
        Me.progressBar.Step = 25

        'プログレスバーの値を増加させるメソッド
        (このメソッドを呼ぶごとに上の増加率がvalueに追加される)
        Me.progressBar.PerformStep()

使い方によっては上手いやりかたがありそう。例えばデータベースに関わるプログラムを作る場合などで、プログレスバーの最大値をdatasetのレコード件数にして、プログレスバーの増加率を1にし、ループ処理中にPerformStep()を組み込むとか・・・・思いつきでやったことはないけれども。

サンプルコード

プログレスバーを使ったサンプルコードを下記に記してみる。使い方としては大体こんなイメージだろうと思う。

        Me.ProgressBar1.Maximum = recordIds.Length
        Me.ProgressBar1.Step = 1
        Me.ProgressBar1.Value = 0
        Me.ProgressBar1.Visible = True

        For i = 0 To (recordIds.Length - 1)
                sqlStr = "UPDATE targetTable SET targetCol = #" & targetVal & "# WHERE targetId = " & recordIds(i)
                obj.execSql(sqlStr)
                Me.ProgressBar1.PerformStep()
        Next i

        Me.ProgressBar1.Visible = False

メモ

現在改良中の家計簿ソフトのデータモデルを変更するかどうかについてのメモ。今のところはmicrosoftのaccessのjetという名前のデータベースでデータを管理している。作る前まではデータを保存する方法といえばこれ一択だった。技術と知識があまりないためだけれども。で、多少慣れてきたのでxml形式でのデータ保存に変更しようかどうか考え中。

microsoft accessを使うことのメリット

  • windowsアプリケーションを作る上では親和性が高い
  • スタンドアロン形式のmdbファイルを使うことができるので外部サーバなどを用意しなくてもよい
  • テーブルやクエリなどの管理が開発者にとっては容易
  • データを一元的に管理できるため楽

microsoft accessを使うことのデメリット

  • ファイルが破損した場合全てのデータが失われる可能性がある
  • ファイルサイズが大きくなった場合に処理速度が低下する可能性
  • オフィスのバージョンアップ毎に機能の変更をチェックしなければならない(?)

今のところ、accessのデメリットというものはあまり感じてない。まあ、accessに限ったことではないし、そうそう壊れるものでもないだろう・・・という楽観的な考えで、バックアップ機能を実装することで最低限これで良しとかいいかげんに考えているからなわけで。それで、accessを使うことをやめてxml形式にした場合にどうなるか考えてみた。

xmlファイルをデータ保存に使うことのメリット

  • microsoft excel 2003以降で開くことができる
  • メモ帳でも開くことができる
  • 別のプログラムで加工して利用するというようなこともできる(かも)
  • mdbに比べてファイルサイズを小さくすることができる(かも)
  • windows以外のコンピュータでも開くことができる

xmlファイルをデータ保存に使うことのデメリット

  • sqlを発行するデータベースに比べてデータの検索や追加などの処理速度が遅くなる可能性がある
  • コード量が割り増ししそうで疲れそう(開発者にとって)
  • データの秘匿・機密性というものがない(私が知らないだけかも・・・)
  • パソコン初心者にはとっつきにくい。

結論

あまり、xmlを使うことのメリットらしいものは思いつかなかった。そもそも初心者向けの家計簿ソフトでxml形式のデータがどうしても欲しいなんていうことはないだろうしなぁ。処理速度が速くなってファイルサイズが小さくなるならxmlファイル形式にすぐにでも変更したいところだけど、そうとも言えないどころかパフォーマンスは悪化しそうだ。excelで開けるといっても年に1回するかどうかもわからない機能のためにこだわるわけにもいかんし。家計簿ソフトのxmlファイル形式への変更は、中止。やっぱり今のままaccessのmdbで運用して、xmlファイル形式に出力できる機能を追加するというのがベストの予感。

datasetの内容をxmlファイルに出力する

datasetの内容をxmlに出力するのにはたった一行、writexmlという関数を使うだけでできあがる模様。あいたたた。datagridにバインドされたデータを一生懸命xml化するためにコードを考えていたのが馬鹿らしくなった。datasetの内容をxmlに変換できるというのは知らないとわからないけれど、xmlデータをdatagridにバインドできるのを知ってたのに逆を想像できなかったのが鈍すぎる。

datasetをxmlファイルに出力するサンプルコード(スマートな方法)

    'datasetを作成するための素材
    Dim cn As New OleDb.OleDbConnection("データベース接続文字列")
    Dim da As OleDb.OleDbDataAdapter
    Dim ds As DataSet

    'datasetにsqlの結果のテーブルをセット
    ds = New DataSet("家計簿")
    da = New OleDb.OleDbDataAdapter("SELECT * FROM 収支", cn)
    da.Fill(ds, "家計簿")

    'datasetにセットされたテーブルをxmlファイル出力
    ds.WriteXml("./data/account.xml")

    'datasetの解放
    da.Dispose()
    ds.Dispose()

datasetをxmlファイルに出力するサンプルコード(悪い見本)

    'datasetを作成するための素材
    Dim cn As New OleDb.OleDbConnection("データベース接続文字列")
    Dim da As OleDb.OleDbDataAdapter
    Dim ds As DataSet

    ds = New DataSet("家計簿")
    da = New OleDb.OleDbDataAdapter(SELECT * FROM 収支, cn)
    da.Fill(ds, "家計簿")

    'xmlドキュメントの宣言
    Dim xmlDoc As New System.Xml.XmlDocument

    'XML宣言
    Dim xmlDecl As System.Xml.XmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", Nothing)

    '宣言を子要素として追加
    xmlDoc.AppendChild(xmlDecl)

    'ルート要素の作成
    Dim rootEle As System.Xml.XmlElement = xmlDoc.CreateElement("家計簿データ")

    'データグリッドのレコード件数をセット
    Dim records As Integer
    Dim i As Integer
    records = ds.Tables(0).Rows.Count
    i = ds.Tables(0).Rows.Count

    '家計簿のレコードの各要素の宣言
    Dim recordElements(i) As XmlElement
    Dim idEle(i) As XmlElement
    Dim dateEle(i) As XmlElement
    Dim catEle(i) As XmlElement
    Dim detEle(i) As XmlElement
    Dim accEle(i) As XmlElement
    Dim moneyEle(i) As XmlElement
    Dim comEle(i) As XmlElement

    'datasetのテーブルからレコードの各値を取り出してノードを作成。レコード件数分ループ。
    For i = 0 To (records - 1)

        recordElements(i) = xmlDoc.CreateElement("レコード")

        dateEle(i) = xmlDoc.CreateElement("入力日")
        dateEle(i).InnerText = ds.Tables(0).Rows(i).Item(0).ToString

        catEle(i) = xmlDoc.CreateElement("費目")
        catEle(i).InnerText = ds.Tables(0).Rows(i).Item(1).ToString

        detEle(i) = xmlDoc.CreateElement("内訳")
        detEle(i).InnerText = ds.Tables(0).Rows(i).Item(2).ToString

        accEle(i) = xmlDoc.CreateElement("口座名称")
        accEle(i).InnerText = ds.Tables(0).Rows(i).Item(3).ToString

        moneyEle(i) = xmlDoc.CreateElement("収支")
        moneyEle(i).InnerText = ds.Tables(0).Rows(i).Item(4).ToString

        comEle(i) = xmlDoc.CreateElement("備考")
        comEle(i).InnerText = ds.Tables(0).Rows(i).Item(5).ToString

        idEle(i) = xmlDoc.CreateElement("id")
        idEle(i).InnerText = ds.Tables(0).Rows(i).Item(6).ToString

        recordElements(i).AppendChild(dateEle(i))
        recordElements(i).AppendChild(catEle(i))
        recordElements(i).AppendChild(detEle(i))
        recordElements(i).AppendChild(accEle(i))
        recordElements(i).AppendChild(moneyEle(i))
        recordElements(i).AppendChild(comEle(i))
        recordElements(i).AppendChild(idEle(i))

        rootEle.AppendChild(recordElements(i))

    Next i

    '作成したルート要素をxmlDocの子要素として追加
    xmlDoc.AppendChild(rootEle)

    '作成したDOMドキュメントをファイルに保存
    xmlDoc.Save("./data/account.xml")

    'datasetの解放
    da.Dispose()
    ds.Dispose()

・・・こんなしんどいことをやろうとしてました(;´д` )

datagridにバインドしたデータが120秒経つと消える・・・

訳の分からない現象が現れた。accessのmdbへselect文を発行して取得したテーブルをdatagridコントロールにバインドするようにプログラムした。そしてデバッグで表示を確かめようとしたところ、一定時間経つとdatagridに一覧表示されていたレコードがフッと消えてしまう。一応時間を計ってみたところ120秒、2分ちょうどで消える・・・。なんだこれは。datagridのプロパティをいじりすぎてぶっ壊してしまったんだろうか。

とりあえず新規にdatagridコントロールを作り直して、みたところ訳の分からない現象は出なくなった。プログラミングのミスではないところのトラブルが対処法がないだけに一番困る。

※原因が判明した。monthcarendarコントロールのdatechangeイベントが悪さをしていた模様。私のプログラムミスでした。datagridコントロール作り直してもよくみたら直ってなかったヽ(´ー`)ノ

datagridの選択した行のセルの値を取得する

備忘。.netframeworks2.0のコントロールであるdatagridコントロールで、バインドされたデータ一覧から選択された行のセル値を取得する方法。datagridのSelectedRowsプロパティを使うとセルの値を取得することができるようになる。SelectedRowsという風に複数形になっているところに気づかなくてしばらく嵌ってしまった。行を複数選択された場合のことも想定されているようなのでインデックスを指定しなければセルの値は取得できない。SelectedRows(0)という風に。

サンプルコード

Dim selectedValue As String
selectedValue = Me.datagrid1.SelectedRows(0).Cells(0).Value

今月の年月の値を取得する

sqlのwhere句に使うための検索条件を作るときに迷ってしまったので覚え書き。まあ、出来てしまえばなんてことは無かったけれど、フォーマットとか関数とか調べても年月のみを取得するメソッドが見当たらなかったので自分で加工するしかなく、datetimeオブジェクトのtoday関数から日付を取得して、それをtostringして、余計な部分をremoveすることで年月のできあがり。下記にサンプルコード。
(昔は文字列の加工やループとかいうものがアレルギーだったけれど、今はもう何の抵抗もなくなっている自分に驚き。慣れってすごい・・・)

サンプルコード

        '今日の日付を取得
        Dim dtYearMonth As DateTime = DateTime.Today

        '取得した今日の日付を文字列型に変換
        Dim str As String = dtYearMonth.ToString

        '年月を取得するために余計な部分を削除
        str = str.Remove(7,11)

        '出来上がりヾ(´ー` )ノ
        MsgBox(str)

サンプルコード2

こういう方法もありかな・・・

        '今日の日付を取得
        Dim today_dates As Date = DateTime.Today

        '今日の日付から年の部分を取り出し。そして文字列型へ変換。
        Dim yearValue As String = today_dates.Year.ToString

        '今日の日付から月の部分を取り出し。format関数で形式を二桁に加工。
        Dim monthValue As String = String.Format("{0:00}", today_dates.Month)

        '年と月の値を合体。
        Dim yearMonthValue As String = yearValue & monthValue

        '出来上がりヾ(´ー` )ノ
        MsgBox(yearMonthValue)

intel mac mini 2Ghz のベンチマークテスト

benchi2.gif2.0GHz Mac mini (MB139J/A)をメモリを2GBへ増設した記念にベンチマークテスト。ベンチマークに使ったソフトはcrystalmarkというソフト。結果は下記の通り。fx55v/bpの6倍のスコアが出てしまった。

MARK 63417
ALU 17228
FPU 20472
MEM 9868
HDD 3704
GDI 4854
D2D 5174
OGL 2117

intel mac mini のメモリ交換

system_propetie.jpg1GBから2GBへメモリの換装を終了。思ったよりも難しかった。あらかじめ他のサイトの分解手順や画像で予習していたものの、実際やってみると予想外の事態に何度も遭遇してしまったため、もう2度とmac miniの筐体は開けたくないと思った。とりあえずは2GBのメモリが認識されてよかったけれど、もう少しで本体を傷だらけにしたうえに最悪再起不能にするところだった。(絶対分解に挑戦した人の中には失敗してmac miniを再起不能にした人がいるはず。それほど簡単な作業とは思えなかった。)

検索語句を表示する

wordpressの検索結果ページ(search.php)に検索に使われた語句を表示してみる。プラグインとかは使わないで、phpのsplit関数とurldecode関数を使ってやることにする。

検索フォームに検索語句を入力し、検索結果ページを表示したとき、その情報はhttp環境変数のQUERY_STRINGを参照することで取得できる。wordpress検索語句の場合は s=%E3%83%86%E3%82%B9%E3%83%88 というような形式で収められている。この’s=’より後の部分が検索に使われた検索語句であるため、その部分を取り出し、urlデコードをかけることで、検索語句を取得することができる。下記にコードのサンプルを参考までに。

サンプル

<?php
  //環境変数から検索に使われた文字列を取り出し。
  $str = $_SERVER["QUERY_STRING"];

  // =で分割して配列に格納する。
  $array = split("=",$str);

  // 配列の1番目をurldecodeして表示する。0番目にはsがあるはず。
  print(urldecode($array[1]));
?>

(余談:この方法はhttpの環境変数から取得して検索語句を取り出している。したがって、環境変数に検索語句が格納されていない場合は当然表示されない。googleなどでインデックスされたページには、なぜかwordpresの検索結果のページが検索結果として表示される(まぎらわしい表現だが)。そういう場合の検索語句も表示したい場合は、javascriptを使って現在表示されているurlを取得→split→urldecodeという流れでやれば、同じようにできる。私はやらない。面倒だから。あくまでもサイト内で検索をした結果の、そのときに使った検索語句を表示することが重要だと思っているので。)