2009年4月30日木曜日

Windows XP でスクリーンセイバーが起動後、ログオン画面を表示させない

スタンバイの設定

Windows XP で、一定時間画面に入力がないと、スタンバイ状態に移行する。その後、PC を起こすと、ログオン画面が表示。その度に一々パスワードを入れるのは面倒 (+_+)

  • 「コントロールパネル > 電源オプション > 詳細設定 > オプション」

の「スタンバイから回復するときにパスワードの入力を求める」のチェックをはずした。

090430-006

 

スクリーンセイバーの設定

しかし、これでもまだ時間が経過すると、ログオン画面が表示されてしまう。

  • デスクトップで右クリック > 画面のプロパティ > スクリーンセーバー > スクリーンセーバー

において、「再開時にようこそ画面に戻る」のチェックをはずすことが必要だった。

090430-005

スクリーンセーバーを意識しなくなって久しいので、こんな設定があることすら知らなかった。 ^^;

そういえば昔ほどスクーンセーバーって聞かないと思えば、以下のような理由がある。

かつては、ディスプレイといえばCRT(ブラウン管)がほとんどで、CRTの焼き付きを防ぐためのユーティリティとして使用されていた。CRT時代の後期には改良が進んだため焼き付きが発生しにくくなり、次第にエンターテイメント的な要素が強くなった。

(スクリーンセーバー – Wikipedia より)

しかし、Download: Windows > アミューズメント > スクリーンセーバ の新着を見ると未だに結構新作があることがわかる。一番新しい「北海道を落とすとどう跳ねるのか?」がおもしろかった。

2009年4月27日月曜日

無線LAN の設定を WEP から WPA へ

1. 無線LAN のセキュリティの設定が甘かった

PC に疎い母曰く、

「うちのインターネットは安全なの?パスワードとか盗まれない?」

急に何事かと思ったら、テレビで無線LAN の危険性について放送していたらしい。

IPA、「情報セキュリティに関する脅威に対する意識調査報告書」を公開 - USBメモリ利用者の3人に1人が未対策 | パソコン | マイコミジャーナル」 によると、

無線LANに関する調査では、利用者の約20%が無線LANの電波が自宅周辺に届く場合があることを認知しておらず、約30%が盗み見の危険性や外部アクセスによる侵入の危険性を認知していないという結果となった。

まぁ、「一応パスワードかけているからいいや」と思っていたけれど、、

無線LANの暗号化方式に関する質問では、利用者の約2割がWEPを利用より解読が難しい WPA2の利用率が6%、暗号化をしていない、またはわからない利用者が約4割という結果となった。

(同上より、装飾は引用者による)

あ! (@_@;) そういえば暗号化の設定が、はじめて無線 LAN を導入したときと、同じ設定のままだった…。 WPA2 ではなく、危険な WEP のまま。

 

2. WEP の危険性

無線LAN – Wikipedia によると、

WEP (Wired Equivalent Privacy) 
無線LAN初期の暗号化規格。共有鍵暗号方式である RC4 が用いられているが、暗号化方式としては脆弱性が指摘され、AirSnortなどのクラッキングソフトが出回っている。

104ビットWEPは1分あれば破れる – スラッシュドット・ジャパン

事実上1分少々あればWEPキーは解読できるということのようだ。

このとき、暗号化の設定をしようと思ったまま放置していた。(+_+)

それにしても、WEP って、全然 Wired Equivalent でないなぁ… ^^;

 

AirSnort について

AirSnort – Wikipedia によると、

これらのソフトの登場によりコンピュータ業界は早急に新たな無線LAN用の暗号化プロトコルを標準化する必要に迫られ、WPA (Wi-Fi Protected Access)IEEE 802.11i (WPA2) といった新たなプロトコルの登場につながっていった

(装飾は引用者による)

AirSnort 等のツールについては、以下を参照。

 

PLC について

無線LAN をやめて、コンセントに挿してネットを利用するタイプ (PLC) に変更しようかとも考えた。しかし、全部揃えたら結構な出費だと思いやめた。 PLC のセキュリティについて、

松下PLCは「屋外へ垂れ流し」「障害窓口ナシ」(電力線通信アダプター発表会後編)」によると、

PLCはとてもセキュリティが高いため、たとえ外に信号が漏れていようとも、データ盗聴やネットの勝手利用のようなトラブルは起きません。松下のHD- PLCではAES128bit暗号技術を使っており、現状では解読不可能と言える高度なものです。

(太字は引用者による)

 

3. どの方式がいいのか? - WPA, WPA2 / TKIP, AES

とにかく省略名が似ているので混乱する。

には同感。(+_+)

無線LAN – Wikipedia よると、 (装飾は引用者による)

WPA (Wi-Fi Protected Access
… WEP での RC4方式に改良が加えられた TKIP (Temporal Key Integrity Protocol)と呼ばれる暗号化方式が採用されている。
WPA2 (Wi-Fi Protected Access 2) 
WPAのセキュリティ強化改良版。… アメリカ標準技術局(NIST)が定めた AES 暗号化方式が採用されている。…

先ほど PLC の説明にも出てきた

AES

という暗号化方式。これがポイントのようだ。

 

4. WPA と WPA2 の違いは?

家で使っている無線LAN の親機は WER-AM54G54

この機種は、サイトの説明にある通り AES に対応している。しかし、これは WPA なのか WPA2 なのだろうか?

PC に挿している子機は WLI-U2-KG54L

こちらは WPA2 と WPA に対応している。説明を見ると、両者ともTKIP/AES となっている。

WPA2とWPAの違いについて - 教えて!goo」 によると、(装飾は引用者による)

  • WPAではAESとTKIPをサポートしているが、WPA2はAESのみ。
    • (TKIPはWEPと同じ暗号化方式をベースとしているため、 AESと比較して解析される危険性が高い)
  • WPA2ではデータの暗号化のみではなく、 CCMPというデータの改ざんを検知する機能を持っている。
  • WPA2はIEEE802.11iの必須項目が実装されている。
  • WPA2はWi-Fiにて認証プログラムがある。
  • WPA2の認証を取得しないと、Wi-Fi CERTIFIEDを取得できない。 (2006年から)

槻ノ木隆の「BBっとWORDS」 の図がわかりやすかった。

 

5. 無線LAN の設定

親機の設定

使用しているルータは、無線LAN|WER-AM54G54

  1. AirStation にアクセスして、
  2. 「無線セキュリティ」の「無線の暗号化」を AES にし、
  3. WPA-PSK を適当に入力。

090427-001

 

子機の設定

クライアントマネージャの方は、

  1. プロファイル > 基本設定」において、
  2. 「暗号化方式」を「WPA-PSK AES 8-63文字」に設定。

ちなみに WPA2-… の設定では接続できなくなった。使っている親機は WPA のみ対応しているということだったようだ。

「暗号キー」には先ほどの WPA-PSK に入力したものを入れた。

090427-002

 

無線LAN 内蔵のノートPC

無線内蔵のノートPC については、

Windows VistaやWindows XP SP3は既にWPA2に対応済みです

( 新年の見直しで,「WPA2」以外の無線LANの暗号化方式は使用禁止に!:ITpro より)

ネットワークの設定を同様に変更するだけだった。

Windows XP の WPA (Wi-Fi Protected Access) セキュリティ更新プログラムの概要(2008年8月14日)

AES のサポート

WPA では、WEP 暗号化の追加の代替として AES (Advanced Encryption Standard) を使用することが規定されています。既存のワイヤレス デバイスのファームウェアの更新プログラムでは AES サポートを追加できない可能性があるため、AES のサポートはオプションであり、製造元のドライバのサポートに依存しています。

これでとりあえず、今できる最低ラインのセキュリティ対策できた。

 

6. 今後どうなるの?

WPA も時間の問題なんだろうか?

あ~、今更ながら、有線にしておけばよかった。(+_+)

 

7. パスワードを忘れた場合

追記(2011.12.23) : WPA で設定したパスワードを忘れた場合、以下のアプリケーションを使うと表示できる。

(via 無線LANのWEP/WPAキーを表示するフリーソフト「WirelessKeyView」 - GIGAZINE)

2009年4月22日水曜日

Access のフォームにおいて、イベントが呼出されるタイミングを知りたい

1. イベントが発生するタイミングを把握する必要がある

Access が分かりにくい理由は、フォームがどういう仕組みの上で動いているかをちゃんと理解せず、場当たりに作ってしまうことにある。フォームに配置できる部品のプロパティを把握しておくことは重要。

フォームのデザインにおいて、

  1. フォームの左上隅をクリックし、
  2. プロパティを表示させると、

色々なイベント処理に対応していることがわかる。

090422-006

しかし、その数があまりにも多く、どういうタイミングで何が呼出されているか理解していないと、簡単にイベント処理の森に迷いこんでしまう。 (@_@;)

イベントの意味、発生する順序について、以下の説明がわかりやすかった。

 

2. Debug.Print で力技

どういうタイミングでイベントが呼出されているのか知りたい。

イベント処理に対して、横からキャッチできないか調べてけれど、分からなかった… (+_+)

仕方がないので、フォームのイベント全部に Debug.Print 書いて、イミディエイト ウィンドウに出力させた。

Private Sub Form_Activate()
    Debug.Print "Activate"
End Sub

Private Sub Form_AfterDelConfirm(Status As Integer)
    Debug.Print "AfterDelConfirm"
End Sub

Private Sub Form_AfterFinalRender(ByVal drawObject As Object)
    Debug.Print "AfterFinalRender"
End Sub

Private Sub Form_AfterInsert()
    Debug.Print "AfterInsert"
End Sub

Private Sub Form_AfterLayout(ByVal drawObject As Object)
    Debug.Print "AfterLayout"
End Sub

Private Sub Form_AfterRender(ByVal drawObject As Object, ByVal chartObject As Object)
    Debug.Print "AfterRender"
End Sub

Private Sub Form_AfterUpdate()
    Debug.Print "AfterUpdate"
End Sub

Private Sub Form_ApplyFilter(Cancel As Integer, ApplyType As Integer)
    Debug.Print "ApplyFilter"
End Sub

Private Sub Form_BeforeDelConfirm(Cancel As Integer, Response As Integer)
    Debug.Print "BeforeDelConfirm"
End Sub

Private Sub Form_BeforeInsert(Cancel As Integer)
    Debug.Print "BeforeInsert"
End Sub

Private Sub Form_BeforeQuery()
    Debug.Print "BeforeQuery"
End Sub

Private Sub Form_BeforeRender(ByVal drawObject As Object, ByVal chartObject As Object, ByVal Cancel As Object)
    Debug.Print "BeforeRender"
End Sub

Private Sub Form_BeforeScreenTip(ByVal ScreenTipText As Object, ByVal SourceObject As Object)
    Debug.Print "BeforeScreenTip"
End Sub

Private Sub Form_BeforeUpdate(Cancel As Integer)
    Debug.Print "BeforeUpdate"
End Sub

Private Sub Form_Click()
    Debug.Print "Click"
End Sub

Private Sub Form_Close()
    Debug.Print "Close"
End Sub

Private Sub Form_CommandBeforeExecute(ByVal Command As Variant, ByVal Cancel As Object)
    Debug.Print "CommandBeforeExecute"
End Sub

Private Sub Form_CommandChecked(ByVal Command As Variant, ByVal Checked As Object)
    Debug.Print "CommandChecked"
End Sub

Private Sub Form_CommandEnabled(ByVal Command As Variant, ByVal Enabled As Object)
    Debug.Print "CommandEnabled"
End Sub

Private Sub Form_CommandExecute(ByVal Command As Variant)
    Debug.Print "CommandExecute"
End Sub

Private Sub Form_Current()
    Debug.Print "Current"
End Sub

Private Sub Form_DataChange(ByVal Reason As Long)
    Debug.Print "DataChange"
End Sub

Private Sub Form_DataSetChange()
    Debug.Print "DataSetChange"
End Sub

Private Sub Form_DblClick(Cancel As Integer)
    Debug.Print "DblClick"
End Sub

Private Sub Form_Deactivate()
    Debug.Print "Deactivate"
End Sub

Private Sub Form_Delete(Cancel As Integer)
    Debug.Print "Delete"
End Sub

Private Sub Form_Dirty(Cancel As Integer)
    Debug.Print "Dirty"
End Sub

Private Sub Form_Error(DataErr As Integer, Response As Integer)
    Debug.Print "Error"
End Sub

Private Sub Form_Filter(Cancel As Integer, FilterType As Integer)
    Debug.Print "Filter"
End Sub

Private Sub Form_GotFocus()
    Debug.Print "GotFocus"
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    Debug.Print "KeyDown"
End Sub

Private Sub Form_KeyPress(KeyAscii As Integer)
    Debug.Print "KeyPress"
End Sub

Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
    Debug.Print "KeyUp"
End Sub

Private Sub Form_Load()
    Debug.Print "Load"
End Sub

Private Sub Form_LostFocus()
    Debug.Print "LostFocus"
End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Debug.Print "MouseDown"
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Debug.Print "MouseMove"
End Sub

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Debug.Print "MouseUp"
End Sub

Private Sub Form_MouseWheel(ByVal Page As Boolean, ByVal Count As Long)
    Debug.Print "MouseWheel"
End Sub

Private Sub Form_OnConnect()
    Debug.Print "OnConnect"
End Sub

Private Sub Form_OnDisconnect()
    Debug.Print "OnDisconnect"
End Sub

Private Sub Form_Open(Cancel As Integer)
    Debug.Print "Open"
End Sub

Private Sub Form_PivotTableChange(ByVal Reason As Long)
    Debug.Print "PivotTableChange"
End Sub

Private Sub Form_Query()
    Debug.Print "Query"
End Sub

Private Sub Form_Resize()
    Debug.Print "Resize"
End Sub

Private Sub Form_SelectionChange()
    Debug.Print "SelectionChange"
End Sub

Private Sub Form_Timer()
    Debug.Print "Timer"
End Sub

Private Sub Form_Undo(Cancel As Integer)
    Debug.Print "Undo"
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Debug.Print "Unload"
End Sub

Private Sub Form_ViewChange(ByVal Reason As Long)
    Debug.Print "ViewChange"
End Sub

あぁ~面倒だった。パタッ(o_ _)o~†

 

3. 試してみる

以下の処理をしたときに、どのようなイベントが発生するか試してみた。

  1. フォームを開く
  2. フィールドを修正
  3. フォームを閉じる

イミディエイト ウィンドウに、以下のように表示された。

Open
Load
Resize
Activate
Current
Dirty
BeforeUpdate
AfterUpdate
Unload
Deactivate
Close

close イベントの前に Before/AfterUpdate イベントが処理されている。Close イベントのときに、Me.Dirty が True でなかったのはこれが理由だったのか。

 

関連記事

Access の VBA でエラー処理

例えば、フォームにレコード を削除するためのボタンがあり、クリックされたときの処理を次のように記述したとする。

Private Sub btnDelete_Click()
    DoCmd.RunCommand acCmdDeleteRecord
End Sub

エラー処理を記述してないので、削除ボタンを押したときに「いいえ」を選択すると、

090422-003

実行時エラーのエラーのダイアログが表示される。

090422-002

 

エラー処理

エラーをキャッチして、エラー番号とエラー内容を表示するように変更するなら、

Private Sub btnDelete_Click()
On Error GoTo Err_Handler
    DoCmd.RunCommand acCmdDeleteRecord
    Exit Sub
    
Err_Handler:
    MsgBox Err.Number & " : " & Err.Description
End Sub

正常に処理されたとき、エラー処理に突入しないように Exit Sub の記述を忘れずに。

先ほどと同じ操作をすると、同じ内容がメッセージボックスに表示される。

090422-004

 

エラー処理の分岐

ところで、ユーザに上記のメッセージを見せる必要はないので、エラーの内容によってエラー処理を変えたい。この場合、先ほどのエラー番号で処理を分ける。

Private Sub btnDelete_Click()
On Error GoTo Err_Hander
    DoCmd.RunCommand acCmdDeleteRecord
    Exit Sub
    
Err_Handler:
    If Err.Number = 2501 Then
        Exit Sub
    Else
        MsgBox Err.Number & "/" & Err.Description
    End If
End Sub

Java ばかりいじっていたとき、エラー番号でトラップするのを見たときびびったけど ^^;

ちなみに Chapter 09 例外処理 - @IT によると、

VB.NETでは、On Error Gotoは「非構造化例外処理」という名前で呼ばれる

 

後処理がある場合

もし、次のような要件がある場合は、

  • エラーの内容に応じて処理をしたい
  • 正常、エラーを問わず後処理が必要
Private Sub btnDelete_Click()
On Error GoTo Err_Handler
    DoCmd.RunCommand acCmdDeleteRecord

Finally:
    ' 後処理
    Exit Sub

Err_Handler:
    If Err.Number = 2501 Then
        ' このエラー独自の処理
    Else
        MsgBox Err.Number & "/" & Err.Description
    End If
    Resume Finally
End Sub

(cf. Access の VBA でトランザクション処理 – CSV ファイルからデータの登録)

処理がシンプルなときは Resume Next でもいいけれど、バグを誘発しそうなので Resume ラベル名 を使うことにしようかな。

2009年4月19日日曜日

Ruby でスクレイピング (2) - Basic 認証を用いたサイトへアクセス

Ruby の Hpricot でスクレイピング」の続き。

1. Basic 認証を用いたサイトをスクレイピングしたい

ルータに割り当てられた IP アドレスを取得したい。

ブラウザでルータの設定画面をアクセスすると、IP アドレスを知ることができる。

ルータの設定画面にアクセスするには、パスワードを入力する必要がある。このときの認証方式は、Basic 認証。

上記を Ruby を用いて、スクレイピングする。

 

2.  方法の概略

  1. Net::HTTP を用いて、Basic 認証を行う。
  2. Hprictot で、HTML  から IP アドレスを表す文字列を抽出する。

 

3. Net:HTTP を用いて Basic 認証を行う

IP アドレスが表示されるページ

090419-018ルータは、AirStation を使っている。最初に、Basic 認証でルータの設定ページにアクセスできるか確かめる。

現在の IP アドレスは、AirStation の

  • 「システム情報」

において表示される。このページはフレームで作成されている。IP アドレスが表示されるのは、右側のフレーム。このフレームだけ表示し、 URL を確認する。

 

Basic 認証

を参考にして Basic 認証を行う。認証を行うには、Net::HTTP::Get クラスを利用する。

Net::HTTPRequest によると、

HTTP リクエストを抽象化するクラスです。Net::HTTPRequest は抽象クラスなので実際にはサブクラスの

  • Net::HTTP::Get
  • Net::HTTP::Post
  • Net::HTTP::Head
  • Net::HTTP::Put

を使用してください。

Net::HTTP を使い、IP アドレスが表示されるページを取得するために、GET リクエストを投げる。

require 'net/https'
require 'kconv'

IP_ADDRESS = '192.168.11.1'
ID = 'root'
PASSWD = 'パスワード'
SETTING_PAGE = '/cgi-bin/cgi?req=frm&frm=info.html'

def getHtml(ip, id, passwd, page)
  req = Net::HTTP::Get.new(page)
  req.basic_auth(id, passwd)
  Net::HTTP.start(ip) do|http|
    response = http.request(req)
    return Kconv.tosjis(response.body)
  end
end

puts getHtml(IP_ADDRESS, ID, PASSWD, SETTING_PAGE)

これにより、「システム情報」のページが出力されることを確認した。

 

4. XPath を利用して、HTML から IP アドレスを抽出する

HMTL から XPath を利用して、要素を取得する関数

次に、上記で取得した HTML を Hpricot で解析。XPath を使って、IP アドレスが書かれた文字列を取得する。

関数 getIpAddress は、HTML から XPath を用いて要素を取得する。

上記の getHtml 関数で得た「システム情報」ページの HTML を、関数 getIpAddress の引数 html 与える。

def getIpAddress(html, xpath)
  doc = Hpricot.parse(html)
  (doc/xpath).each do |td|
   return $1 if /(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ =~ td.inner_html
  end
end

XPATH = '/html/body/form/table/tr[3]/td[2]/table/tr[5]/td[2]'
puts getIpAddress(html, XPATH)

これにより、IP アドレスが表示された。

 

Firebug で XPath を取得

XPath を記述するために、Firefox のアドオン Firebug を利用した。 Firebug で XPath を得るには、

  1. HTML の要素を選択し、
  2. 「右クリック > XPath をコピー」。

取得した XPath は、以下の通り。

/html/body/form/table/tbody/tr[3]/td[2]/table/tbody/tr[5]/td[2]

しかし、Hpricot で、この XPath を用いて IP アドレスを取得できなかった。

 

Firefox, Google Chrome で自動的に挿入される HTML 要素

なぜか上記の XPath から `tbody’ を削除することによって、要素を取得できた。

これは、http://ircarchive.info/ruby-lang/2007/4/12/10.html によると、

firefox inserts tbodies after tables if they're not there

Firefox は、table 要素の後に tbody 要素がないと、tbody 要素を挿入する。

試しに、HTML で tbody 要素を書かずに table を書き、Firebug で確かめたら、確かに tbody が挿入されているのを確認した。 Google Chrome も同じ現象が生じた。

 

5. 全体のソースコード

require 'net/https'
require 'kconv'
require 'hpricot'

# ルータの IP アドレス
IP_ADDRESS = '192.168.11.1'
# Basic 認証のための ID とパスワード
ID = 'root'
PASSWD = ''
# 「システム情報」のページ
SETTING_PAGE = '/cgi-bin/cgi?req=frm&frm=info.html'

# IP アドレスを取得するための XPath
XPATH = '/html/body/form/table/tr[3]/td[2]/table/tr[5]/td[2]'

def getHtml(ip, id, passwd, page)
  req = Net::HTTP::Get.new(page)
  req.basic_auth(id, passwd)
  Net::HTTP.start(ip) do|http|
    response = http.request(req)
    return Kconv.tosjis(response.body)
  end
end

def getIpAddress(html, xpath)
  doc = Hpricot.parse(html)
  (doc/xpath).each do |td|
   return $1 if /(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ =~ td.inner_html
  end
end

html = getHtml(IP_ADDRESS, ID, PASSWD, SETTING_PAGE)
puts getIpAddress(html, XPATH)

2009年4月18日土曜日

Firefox でタブの切り替えに FoxTab - タブの一覧をサムネイルで表示する

1. タブを切り替えるために、サムネイルを利用したい

ブラウザで、興味の赴くままたくさんのサイトを同時に見ていると、悩ましいのがタブの切り替え。タブをいくつも開いていると、どこに何を開いていたか分からなくなる。

Firefox であれば、TabMixPlus を使いタブを多段に表示させることができる。しかし、それも視認性の限界がある。たくさんタブがあると、目的のものを探すのに時間がかかる。

タブの切り替えに、デフォルトではドロップダウンメニューにより、タイトルを一覧を表示してくれる。この方法は、文字を一々読まないといけないので、さっと切り替えるのに向かない。一覧に favicon も表示されるが、それだけでは素早く切り替えるためには情報不足。 (+_+)

これを解消するために、アドオン「タブカタログ」を利用していたことがあるタブカタログは、開いているタブのサムネイルを表示してくれる。

タブを切り替えたいとき、

「さっきまで読んでいた、あのサイトの記事を読みたい…」

という要求の元に行われる。そのとき、最初に思い出すのは、読んでいたサイトの全体的なイメージ。人は、大雑把なイメージ情報を保持しているのは得意。タイトルよりもサイト全体の「感じ」を記憶している。そのため、見ていたページのサムネイルを再認はしやすい。

 

2. アドオン FoxTab でタブを切り替える

 FoxTab は、タブカタログを更に高機能にしたアドオン。

アドオンの説明をはじめ読んだとき、Cooliris の新しいバージョンかな?と思った。

FoxTab は、ユーザが自分好みに表示やショートカットをカスタマイズできるところがいい。

 

a. 表示のカスタマイズ

FoxTab の表示をカスタマイズするために、

  • 右クリック > FoxTab をクリック。

3D 表示も魅力的だったが、シンプルなタイル表示を選択した。

090418-012

次に、左隅の 090418-011 歯車のアイコンから、設定ダイアログを呼出す。

デフォルトでは、サムネイルがブラウザの画面に表示される。画面一杯にサムネイルを表示させたいので、

  • Size > Size Full Screen

にした。

090418-004

サムネイルをぱっと見て、サイトを把握するために、

  • Layout > Layout より大きさ・行数・列数

の設定を調整した。

090418-008

直近に表示していたタブが、左上に来てくれると探しやすい。

  •  General > View > Arrange tabs by most recently used order

にチェックを入れた。

090418-009

 

b. ショートカットキーの設定

FoxTab を呼出すためにショートカットを設定した。この設定をカスタマイズできたから、FoxTab を使うことにした。

ショートカットキーを離しても FoxTab が表示され続けるように設定。

  • Shortcuts > Interactive Panel Launch の方をいじる。

FoxTab を起動するショートカットキーは、

  • Ctrl + e

とした。ショートカットキー Ctrl + W は、デフォルトで「タブを閉じる」動作に割り当てられている。。 W の隣にある `e’ を使うことにより、タブを閉じるときは中指を押さえ、タブの一覧を表示するときは人指し指で押すと覚えた。

090418-007

 

c. 検索とグループ化

便利な機能は、

Ctrl + F

により、タイトルからタブを検索して抽出できること。文字を入力した瞬間に抽出のアニメーションがはじまるところがカッコイイし、実用的。 ^^

デフォルトでは、

Ctrl + G

で、タブをドメインごとに分類してくれる。表示されている順序の方が見やすいので、

  • Groups > Groups > Sort Groups By: 

Tabs Orders に変更した。

090418-010

 

3. タブのサムネイルが表示されない場合

追記(2013/07/05): FoxTab が動作しなくなった場合、Flash の設定画面で、Firefox の「プロファイル」フォルダを「信頼されている場所」に設定する。

「コントロールパネル > システムとセキュリティ > Flash Player > 高度な設定 > 信頼されている場所設定」に「プロファイル」フォルダを追加する。

追記(2013/07/06): Firefox を起動した後、はじめて FoxTab を立ち上げるためには、なぜか「左端にあるタブ」をアクティブにしなければ、正常に表示されない。

 

関連記事

時刻を扱う - 特定の日付に属さない時間

例えば、「いつも朝の 6:30 から 6:40 までラジオ体操をする」という事柄を表現したいとする。「いつも」とあるように、この表現は特定の日付と関連したものではない。過去のある期間においてそういう事実があったことを記録したいわけでもなく、未来の予定について述べているわけでもない。「日常」という言葉通り、典型的な「生活パターン」というような抽象的なレベルの事象をどのように表現して扱うかという問題。

 

Access の日付/時刻型

さて、Access でデータを管理しようと思うと、上記の「時刻」をどのデータ型で扱えばいいのだろうか?最初に思い付くが「日付/時刻型」。(cf.  Access で使用できるフィールドのデータ型 (MDB) - Access - Microsoft Office Online)

「日常生活」と命名したテーブルを以下のように定義し、

090417-001

データを入力したとする。

090417-002

 

これに対して、次のように「年月日」を表示させるクエリを実行すると、

SELECT 日常生活.id, 日常生活.内容, Format([開始時刻],"yyyy/mm/dd hh:nn") AS 式1, Format([終了時刻],"yyyy/mm/dd hh:nn") AS 式2
FROM 日常生活;

時刻の前に `1899/12/30’ が表示される。これでは表現したいデータを素直に表現しているとは言い難い。 (+_+)

090417-003

ちなみにこの日付となる理由は、「フィールドのデータ型の設定を修正または変更する - Access - Microsoft Office Online」によると、

Access では、1899 年 12 月 30 日が日付 0 として使用されます。

 

時間について

プログラマのためのSQL 第2版 (P64) によると、

時間に関する重要な問題の 1 つに、時間には 3 種あるというのがあります。固定された出来事「彼は、13:00 に到着した」、期間「その旅は 3 時間かかる」、時間間隔「その列車は 10:00 に出発して 13:00 に到着する」は、それぞれ依存関係を持っています。 SQL-92 は、 INTERVAL データ型を導入していますが、ほとんどの現実の実装 (…) では、明白に持っていません。

(太文字は引用者による)

SQL – Wikipedia を見ると、SQL-92 で INTERVAL が追加されているのがわかる。

データ型の拡張 (可変長文字列、ビット、文字集合、日付・時刻・時間間隔 (DATE, TIME, TIMESTAMP, INTERVAL))

どうやらこの「時間間隔」というのが考える手がかりになりそうだ。

ちなみに Access と SQL のデータ型を比較した表を見ると、Access では INTERVAL 型を直接表現した型がないことがわかる。

 

ところで、Access ではユーザ定義型を作成することができない。(型とその型に適用できる演算子の定義がまともにできる RDB ってどれくらいあるのだろう?) よって、上記の要求を満たすドメインの値を素直に保持することはできない。そのため、結果として機能し得る型で代用することになる。

 

MySQL の Time 型

MySQL :: MySQL 5.1 Reference Manual :: 10.3.2 The TIME Type によると、

MySQL retrieves and displays TIME values in 'HH:MM:SS' format (or 'HHH:MM:SS' format for large hours values). TIME values may range from '-838:59:59' to '838:59:59'. The hours part may be so large because the TIME type can be used not only to represent a time of day (which must be less than 24 hours), but also elapsed time or a time interval between two events (which may be much greater than 24 hours, or even negative).

MySQL 5.1 では「時間間隔」と「一日の時刻」を同じ Time 型で表わすようだ。というより、「一日の時刻」を「時間間隔」で代用しているということかな。

 

Postgres の interval 型と time 型

Postgres は、「時間間隔」 (Interval) と「その日の時刻」(time) が分かれている。

 

Python の time オブジェクト

ところで、以前に Python で指定した日数後の日付を得るのに timedelta オブジェクト を使ったことがある。timedelta 周りを見ると time オブジェクト があるのに気がついた。(@_@)

time クラスは、

理想化された時刻表現で、あらゆる特定の日における影響から独立しており、毎日厳密に 24*60*60 秒であると仮定します ("うるう秒: leap seconds" の概念はありません)。 属性: hourminutesecondmicrosecond、 および tzinfo

(5.1.1 利用可能なデータ型 より)

まさにこれ。ただし、

time オブジェクト間の四則演算はサポートされていないので注意してください。

(time オブジェクト より)

「年月日」がなく「時・分・秒」だけので、上記の例を表現するには概念的にちょうどいい。

 

Visual Basic の日付

VB にも、似たような見かけの TimeSerial 関数 があったが、

    Debug.Print TimeSerial(6, 30, 0)
    Debug.Print Format(TimeSerial(6, 30, 0), "yyyy/mm/dd hh:nn")

実行すると、

6:30:00 
1899/12/30 06:30

あ~、内部では日付型かぁ…

@IT:連載:プロフェッショナルVB.NETプログラミング 第5回 日付時刻の取得とフォーマット によると、

日付と時刻の扱いは、Microsoft系BASICの歴史に限ってもすでに激変が起きている。初期のBASICでは、日付と時刻はそれぞれ文字列として扱われており、日付と時刻は別個の情報として扱われていた。(…)

Timeの場合日付は1899年12月30日となっているが、これはVB 6の日付を扱う起点となる日付である。(…)

VB.NETでは日付時刻の起点は0001/01/01 12:00:00である

うーむ… (@_@;)

 

Haskell の TimeOfDay 型

では、Haskell ではどうかな?と思い調べてみると、Time of day に、

data TimeOfDay

Time of day as represented in hour, minute and second (with picoseconds), typically used to express local time of day.

「時・分・秒」のみを値に持つ型がある。

先ほどの Python の Time オブジェクトと同様に、TimeOfDay 型は Num クラスのインスタンスではないので四則演算はできない。ただし、DiffTime 型という「時間間隔」を表わす型を利用すると計算を行うことができる。

最初に timeOfDayToTime 関数で TimeOfDay 型を DiffTime 型に変換。この関数は午前 0 時からの時間間隔を返してくれる。

timeOfDayToTime :: TimeOfDay -> DiffTime

090417-001

DiffTime 型は Num クラスのインスタンスなので、この型の値を足したり引いたりできる。それを上記の関数とは逆の timeToTimeOfDay で元の型に戻す。例えば、

import Data.Time
main = do
  let s = TimeOfDay 6 30 0
  print s
  let ds = timeOfDayToTime s
  print ds
  print $ timeToTimeOfDay $ ds + (secondsToDiffTime (10*60))

結果は、

06:30:00
23400s
06:40:00

 

対応する型がない場合の妥協

さて、話を元に戻して Access で時刻を扱うにはどうしよう。

一つは、年月日の情報は無視して、つまり ‘1899/12/30’ はないものとして時刻だけを「日付/時刻型」で扱う。とりあえず楽な方法。

自前でどうにかしたいなら、「時・分・秒」をそれぞれ別のフィールドで数値として扱い、それを一塊のものとして自分で思い込み、「時・分・秒」間での計算が必要なら関数を定義。ちょっと面倒だし、それに見合ういいことがあるのかわからない。

また別の方法として、NULL撲滅委員会 にあるように、

日付の列は文字型で宣言しておくべきです。(…) ほとんどの DBMS が日付型を用意していますが、私は個人的に使うメリットを感じません。暦日計算の場合など、必要なときだけキャストしています。

時刻を文字列として保持し、必要なときだけキャストする。ただし、年月日の情報は無視して日付型として計算を行う。この場合、最低でも文字列として時刻を保存するとき、時刻へとキャスト可能な形式であるか確認する必要となる。

2009年4月16日木曜日

Access の VBA でトランザクション処理 – CSV ファイルからデータの登録

トランザクションと言えば、やはりこの本。

未だ買ってすらいない。 パタッ(o_ _)o~†

昔からデータベースのこの辺がチンプンカンプン。入門レベルを読んでもトランザクション、排他制御になるとついていけない。いつかはちゃんと頭の中を整理したいのだけれど… (+_+)

 

クライアントから見たトランザクション

トランザクションの大枠については以下の図を参照。

異常なければコミット、異常があればロールバック。これだけ聞くとシンプルなのだけれど…。とりあえず、クライアントアプリがトランザクションを利用するときのテンプレートを書いておくことに。参考にしたのは以下の二つの記事。

Access の ADO については、「ActiveX Data Object : ADO入門講座」を。

 

テンプレート

以下、ADO でテーブルにレコードを追加するときのテンプレート。Java のように try ~ catch がないのでエラーハンドラと Resume を利用。

ポイントは、トランザクションが開始された後に異常が置きたらロールバック。正常異常を問わず、最後にデータベースへのコネクションを閉じる。ただし、その際コネクションが存在していることを確認すること。

Sub tmplADOTran()
On Error GoTo Err_Handler
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim blnTran As Boolean
    
    blnTran = False
    
    Set cn = CurrentProject.Connection
    Set rs = New ADODB.Recordset
    
    ' トランザクションの開始
    cn.BeginTrans                   '
    blnTran = True

    rs.Open "テーブル名", cn, adOpenKeyset, adLockOptimistic
    
    ' データを列ごとに追加する
    rs.addnew
    rs!列名 = "値"
    rs.Update
    
    ' コミット
    cn.CommitTrans
    blnTran = False
    
Finally:
    If Not rs Is Nothing Then rs.Close
    If Not rs Is Nothing Then cn.Close
    
    Exit Sub
    
Err_Handler:
    ' ロールバック
    If blnTran Then cn.RollbackTrans
    MsgBox "エラーが発生しました: " & Err.Description, vbOKOnly
    
    Resume Finally
End Sub

あぁ~、何かややこしいなぁ。 (+_+)

 

例. CSV ファイルのデータを登録

上記のテンプレートを元に、CSV ファイル (test.csv) のデータをテーブルに登録するコードを書いてみる。ただし、対象のテーブルは一つ。追加する先のテーブルの列は文字列型とする。

まず、データを追加するテーブルの名称と列の名前を保持する Table クラスを作成。(挿入 > クラスモジュール) 値を保持するだけなのでインスタンス変数は Public に。

Public name As String               ' テーブルの名称
Public cols As New Collection       ' 列の名前のコレクション

上記のテーブル情報を持ったオブジェクトと、データ元となるファイルへのパスを渡すとレコードを追加する関数は以下のようになる。

Sub insert(objTbl As table, strFilePath As String)
On Error GoTo Err_Handler
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim blnTran As Boolean
    
    Dim fileNo As Integer
    Dim idx As Integer
    
    blnTran = False
    
    Set cn = CurrentProject.Connection
    Set rs = New ADODB.Recordset
    
    ' トランザクションの開始
    cn.BeginTrans                   '
    blnTran = True

    rs.Open objTbl.name, cn, adOpenKeyset, adLockOptimistic
    
    ' CSV ファイルからデータを一行ずつ読み込む
    fileNo = FreeFile()
    Open strFilePath For Input As #fileNo
    Do Until EOF(fileNo)
        Line Input #fileNo, strLine
        strAry = Split(strLine, ",")
        
        ' データを列ごとに追加する
        rs.addnew
        
        idx = 0
        For Each col In objTbl.cols
            rs(col) = strAry(idx)
            idx = idx + 1
        Next
        
        rs.Update
    Loop
    Close #intFileNo
    
    ' コミット
    cn.CommitTrans
    blnTran = False
    
Finally:
    If Not rs Is Nothing Then rs.Close
    If Not rs Is Nothing Then cn.Close
    
    Exit Sub
    
Err_Handler:
    ' ロールバック
    If blnTran Then cn.RollbackTrans
    MsgBox "エラーが発生しました: " & Err.Description, vbOKOnly
    
    Resume Finally
End Sub

上記を例えば次のように呼ぶ。

Sub test()
    Dim objTbl As New table
    Dim filePath As String
    
    ' CSV ファイルのパス
    filePath = Application.CurrentProject.Path & "\test.csv"
    
    objTbl.name = "テーブル名"        ' データを追加するテーブルの名前
    objTbl.cols.Add "列名"      ' データを追加するテーブルの列の名前
    
    insert objTbl, filePath
End Sub

 

参考

2009年4月14日火曜日

ACCESS で生年月日から年齢を求める

1. 「人」テーブルの定義

以下のような、「人」テーブルがあるとする。

  1. id : 主キー
  2. 名前
  3. 性別id : 01 男、02 女
  4. 生年月日

090413-001

各々の「人」に対して、次のことを知りたい。

  • 現在の年齢
  • 今年度末に何歳になるか?

 

2. 年齢を求めるための関数を定義

現在の年齢を求める関数

生年月日から年齢を求めるには、

「今年の誕生日が来ているかどうか?」

がわかればよい。

そのため、

  1. 「指定された日付に、何歳になっているか求める」関数を定義し、
  2. 現在の日付を渡すことによって、
  3. 今の年齢を求める。

関数の定義は、

  • 「データベース > モジュール」

において、新規モジュールを作成する。

日付の関数については

を参考にした。

' ある誕生日の人が、指定した日付に何歳になっているか返す。
Function Age(birthday As Date, theDate As Date) As Integer
    If AfterThisYearsBirthday(birthday, theDate) Then
        Age = Year(theDate) - Year(birthday)
    Else
        Age = Year(theDate) - Year(birthday) - 1
    End If
End Function

' 指定された日付に今年の誕生日が来ているか?
Function AfterThisYearsBirthday(birthday As Date, theDate As Date) As Boolean
    If Month(birthday) < Month(theDate) Or _
        (Month(birthday) = Month(theDate) And Day(birthday) <= Day(theDate)) Then
        AfterThisYearsBirthday = True
    Else
        AfterThisYearsBirthday = False
    End If
End Function

 

年度末における年齢を求める関数

次に、年度末に何歳になっているか知りたい。

上記と同様に「指定された日付の年度末を返す」関数を書く。

' 指定された日付の年度末の日付を返す
Function Nendomatu(theDate As Date) As Date
    Const DATE_331 = "/3/31"
    If 4 <= Month(theDate) And Month(theDate) <= 12 Then
        Nendomatu = CDate(Year(theDate) + 1 & DATE_331)
    Else
        Nendomatu = CDate(Year(theDate) & DATE_331)
    End If
End Function

 

3. クエリから関数を呼び出す

上記の関数を、クエリから呼出すようにする。

  1. 「人」テーブルを対象にしたクエリを作成し、
  2. 「年齢、年度末の年齢」を求めたい列で、右クリック > ビルド... を選択し、
  3. 式ビルダを呼出す。

左下を見ると、「関数」フォルダに、先ほど作成したモジュール名が表示され、定義した関数が属しているのがわかる。

090413-003

それぞれ以下のように定義する。

年齢: Age([生年月日],Now())
年度末の年齢: Age([生年月日],Nendomatu(Now()))

クエリの結果。今日の日付は 2009.4.13 。

090413-002

 追記(2009.4.25) : 学校の学年においては、 4/1 生まれは早生まれになるので、年度末の翌日における年齢を求める。

年度末の年齢: Age([生年月日],nendomatu(Now())+1)

(参考: 法制執務コラム集「4月1日生まれの子どもは早生まれ?」)

 

4. クエリの中だけで計算するには

生年月日から年齢を計算する方法」には、次のようなクエリが書かれていた

年齢: IIf(Right(Format([誕生日],"yyyy/mm/dd"),5)>Right(Format(Now(),
"yyyy/mm/dd"),5),DateDiff("yyyy",[誕生日],Now())-1,DateDiff("yyyy",
[誕生日],Now()))

(via 生年月日の入力によって年齢を出したい。 --Access Club 超初心者 FORUM—)

うへぇ~、一行だと読みにくい… (+_+)

そもそも、これは何だろう?

Right(Format([誕生日],"yyyy/mm/dd"),5)

関数をテストしてみる。

    Debug.Print CDate("1/1")    ‘ 2009/01/01  
    Debug.Print CDate("1")      ‘ 1899/12/31 
    Debug.Print CDate("366")    ‘ 1900/12/31 
    Debug.Print CDate("0")      ‘ 0:00:00 

CDate のヘルプを見ると、

CDate    日付型 (Date)    任意の有効な日付式

「日付式」とは、

日付として解釈可能な式。… 日付と解釈できる文字列、

結果を見ると、そこまで無理に解釈しなくても…と言いたくなるような仕様。 ^^;

日付の内、「年」を省略すると、「現在の年」と解釈されるようだ。

 

5. シンプルな計算方法

生年月日から年齢を計算する簡単な計算式:ITpro」には、次のような計算式が書かれている。

(今日の日付-誕生日)/10000の小数点以下切捨て。

なるほど、「年月日」をわざと一連の数値として扱う方法のようだ。確かに、年月だけ見れば、年月を各々二桁で表現しているなら、誕生日が来ていれば、今日の日付よりも誕生日の数値が小さくなる。

先ほどの方法でパフォーマンスが悪ければ、こちらに変更しようかな。

ただし、次の注意点が述べられている。

「誕生日の前日が終了する瞬間(すなわち誕生日をむかえる午前0時00分の直前)に1歳を加えることになる」の部分の解釈には前日に1日加えると解釈される場合と当日に1日加えると解釈される場合の2種類があるようです。特に自治体においては前者で解釈される場合が多いとのことです。

(同上より)

ん?これは自治体の特殊ルールで、「年齢」と「年齢をどう解釈するか」とは別の話だよねぇ。

Gmail で画像を D&D で挿入

Gmail で図を使った説明を送ろうとすると、画像を添付するしかなかったので不満だった。しかし、「Google Japan Blog: Gmail Labs の新機能: 画像の挿入」によると、

「Gmail で添付ファイルではなく本文内に画像を挿入したい」というリクエストをいただいます。…. 今回あらたに Gmail Labs に加わった「画像の挿入」は、まさにそれを実現するものです。

おぉ~、これで普通のメールクライアントのような操作ができる。 ^^ 早速「Labs」タブでこの機能を有効に。

 

Firefox のアドオン dragdropupload を使えば画像を D&D できる。これでもう Thunderbird はアンインストールしようかなぁ。

2009年4月13日月曜日

GA-MA78GM-S2H の BIOS を F7 にアップデート

メモリを増設したことによって、アプリケーションの切り替えはスムーズに行くようになった。メモリ使用量が 2G を超えてもサクサク動くから快適ぃ~と思っていたのも束の間。あぁ、人間の慣れというものが恨めしい。メモリがボトルネックになっていたのが、今度は CPU の処理能力が気になるように。最近は気温も徐々に上昇し、また熱対策の季節がすぐそこまで来ているのを感じる。 (@_@;) このままオーバークロックした状態では持たないだろうなぁ。 (+_+)

 

Phenom II X3 720 Black Edition

自作 PC 関係のニュースを読まなくなってしばらく経つが、最近の AMD はどうなんだろう? 組んだときは Phenom いいなぁ~と思いつつ、値段は高いし、発熱量は多いし、何だかエラーがどうのこうのという話があったので、廉価な AMD Athlon 64 X2 Dual-Core 5000+ Black Edition を選んだ。今はどの CPU が売れているのだろうかと検索してみたら、AMD Phenom II がいいらしい。

 

古田雄介のアキバPickUp!:「全然微妙じゃなかった」――Phenom II X3が大ヒット中 (1/4) - ITmedia +D PC USER によると、

Phenom II X3 720 Black Editionは2.8GHzで動作するトリプルコアCPUで、6MバイトのL3キャッシュを搭載している。登場当初は「動作クロック倍率可変の Black Editionといえども、しょせんはトリプルコア。やはりクアッドコアを待つユーザーが多い」(TSUKUMO eX.)などのコメントが多く、ヒットとはほど遠い状況だった。

そこから一転して大ブレイクとなったのは、ある情報が広まったことがきっかけだ。パソコンショップ・アークは「Phenom II X3はもともとクアッドコア構成なのを1コア無効にしているだけなんです。それでBIOS設定を少しいじるだけで1コア復活できるという情報が流れ、いきなり飛ぶように売れ始めました」と語る。

AMD Phenom II X3 720 Black Edition BOX 評価・レビュー [coneco.net] を見ても評価が高い。

 

BIOS とマザーボードのリビジョン

値段もそこそこなので CPU 変えるならこれだなぁ~と思っても、果たして自分のマザーボードは対応しているのだろうかとチェック。ギガバイト - サポート - マザーボード - CPUサポートリスト - GA-MA78GM-S2H (rev.1.0) を見ると、BIOS を `F7’ にすれば対応できるようだ。

ちなみにこのマザーボード、以下のようにリビジョンがあり、

【AMD780】GIGABYTE GA-MA78GM-S2H Part6 によると、

78GM-S2H Rev1.0 VRM3+1 125Wまで対応、基本モデル
78GM-S2H Rev1.1 ヒートシンク変更&IGPファンpin追加
78GM-S2H Rev2.0 VRM4+1に強化140W対応,DualBIOS対応

はじめて組んだ自作 PC だったので、同じマザーボードでもこういう違いがあるというのは知らなかった。 (@_@;)

 

BIOS の更新はちょっと…

ところで、BIOS のアップデート作業をしたことない。そもそも自分のはバージョンがいくつなのだろうかと CPU-Z で調べてみると `F3’ だった。BIOS のアップデートと言うと、フロッピーを使い、もし失敗したら大変なことになるというイメージがあったので、これまでずっと二の足を踏んでいた。しかし、ATI のドライバを更新したら PC の動きが良くなったし、いつかは Phenom に交換したいなぁ~という思いから、BIOS のアップデートを試してみることにした。最悪起動しなくなったときの場合を考えてバックアップ等をしないといけないだろうけれど、ちょっと面倒なのでパス。 ^^; いちかばちかでやってやる。

 

USB メモリを使って BIOS の更新

アップデートの方法は「GIGABYTEマザーのBIOSアップデート方法 (Q-FLASH使用text) :: B Stage BLOG」の説明が丁寧でわかりやすかった。ここではじめて USB メモリ を使ってアップデートできることを知る。マザーボードに付属していた説明書の「4-2 BIOS Update Utilities」(p64) を確認すると、

Extract the file and save the new BIOS file (…) to your floppy disk, USB flash drive, or hard drive.

これならお手軽にできそうだ。 ^^

 

ギガバイト - サポート - マザーボード - BIOS -(rev.1.0) を見ると、最新の BIOS は `F8a’ となっているが、最後の小文字の `a’ が気になるので、一つ前の `F7’ を適用することにした。

ダウンロードしたものを解凍し、USB メモリに入れたら PC を再起動して BIOS 画面に入る。F8 キーを押して Q-Flash を起動し、Update BIOS from Drive > HDD 1-0 を選んだら USB メモリに入れたアップデート ファイル が表示された。

DSC02302

後は指示に従っているとアップデートが進み、

DSC02303

トラブルもなく、拍子抜けするほど簡単に終了。

 

確認

CPU-Z で確認してみると、BIOS のバージョンが F7 に変わったことがわかる。

090413-001

 

Chipset driver

ところで、BIOS のアップデートの履歴を見ると `F4’ において

* For F4 BIOS, please also update the AMD Chipset driver to version 8.470 or later.

これも必要なのかな?と思いインストールしてみた。そうしたら、以前と同じように Firefox の描画がもたつくようになったので、再度 ATI Catalyst 9.4 にアップデート しなおした。

2009年4月11日土曜日

ATI Catalyst 9.4 にアップデート

AMDは,同社製のデスクトップPC向けGPUおよびチップセット製品に対応するドライバスイート,「ATI Catalyst」の最新版,「ATI Catalyst 9.4」(以下,Catalyst 9.4)を公開した。

(4Gamer.net ― HD 4890に正式対応した「ATI Catalyst 9.4」公開。ATI Radeon X1000以前のGPUがサポート対象から外れる(ATI Catalyst) より)

以前、Firefox における描画のもたつきが、アップデートによって改善された。前回のアップデータのバージョンが 8.12 で、4Gamer.net で紹介されていたのが 2008.12.11 なので、短い期間に結構アップデートされるものなんだなぁ~。

4Gamer.net を見ると、8.12 以降、

とあったようだけれど全然気づいてなかった。

前回と同様にダウンロードしてインストールしたら、Cooliris と最近愛用している FoxTab、それに DExposE2 の動作が前より良くなった。 ^^

2009年4月8日水曜日

Python で MySQL を操作 – MySQL-python

1. MySQL を Python で操作するためのライブラリ

Python で MySQL のデータを操作したい。

MySQL - PythonInfo Wiki によると、以下の 3 つのライブラリが挙げられていた。

とりあえず、一番上を使ってみよう。

 

2. MySQL for Python のダウンロードとインストール

をダウンロードしてインストール。

090407-003

\Lib\site-packages\ にインストールされる。

 

3. Python Database API Specification

MySQLdb User's Guide によると、

If you want to write applications which are portable across databases, use MySQLdb, and avoid using this module directly. _mysql provides an interface which mostly implements the MySQL C API.

_mysqlMySQLdb の二つのインターフェイスがある。データベース間で、統一したインターフェイスを持つことを目的にされた MySQLdb は、

を実装している。

Some examples を参考にしながら試すことにした。

 

4. 例

郵便番号のデータ を MySQL に登録してみる。

CSV ファイルのデータ形式は、郵便番号データファイルの形式等 を参考にした。このデータから、以下の項目を抽出する。

  • 郵便番号(7桁)
  • 都道府県名
  • 市区町村名
  • 町域名
方法

まずは、MySQL Administrator を使って、以下のような yuubinbangou テーブルを作成。

090407-004

コードを以下に示す。

  1. 最初にテーブルのデータを削除し、
  2. CSV ファイルから 100 件分のデータを登録した後、
  3. 登録したデータ 10 件分を表示するようにした。

(郵便番号のデータは C: 直下に配置。)

import MySQLdb, codecs

# DB に接続
db = MySQLdb.connect(user="test", passwd="test", db="test", charset="utf8")
# カーソルの取得
c = db.cursor()

# DELETE
c.execute("delete from yuubinbangou")

# INSERT (最初から 100 件分を登録)
FILE_PATH = ur"C:\KEN_ALL.CSV"
f = codecs.open(FILE_PATH, "r", "shift_jis")
for i in range(0,100):
    row = [x[1:-1] for x in f.readline().split(',')]
    c.execute(u"""INSERT INTO yuubinbangou(bangou, ken, si, tyou)
                VALUES ('%s', '%s', '%s', '%s')"""
                % (row[2], row[6], row[7], row[8]))
f.close()

# COMMIT
db.commit()

# SELECT
c.execute("SELECT * FROM yuubinbangou")
# 最初から 10 件を表示
it = iter(c)
for i in range(0,10):
    for col in it.next():
        print col,
    print

 

コードについて

データベースに接続する connect メソッドの引数に、

charset="utf8"

を追加しないと、UnicodeEncodeError が投げられた。

その他、以下を参照。

MySQL で文字化け - 後から文字コードを変えるとき」のようなミスをしないように。 (+_+)

2009年4月7日火曜日

MySQL で文字化け - 後から文字コードを変えるとき

my.ini の設定で (WinMySQLadmin の my.ini Setup タブ)

[mysqld]
default-character-set=utf8

を追加せずに MySQL Administrator でテーブルを作成したら、文字コードが latin1 となった。これに気がつかずデータを挿入したので文字化け。

 

これではいけないと思い Table OptionsCharacter Set を `utf8’ に変更。これにより新規に列を作った場合、列の Character Set は utf8 になる。

090407-002

 

しかし、変更前に作成した列は latin1 のままなので、Column Charset も utf8 に変更する必要がある。

090407-003

 

Access から MySQL にデータを追加すると文字化けするなぁと思ったら、こんなことが原因だったとは…。あぁ~、余計な時間を… (+_+)

 

関連記事

2009年4月6日月曜日

C# をはじめるための準備 - Visual Studio と SQL Server のインストール

お手軽に GUI を構築できるツール

久しぶりに Access を触っていると、シンプルなものならチャチャッと DB を作り、データ入力画面のデザインにこだわらず無骨なままで、必要なレポートを適当に出力させるという使い方をする分には便利だなぁと思う。プログラミングを全く知らないとき、FileMaker を使って給料計算をするためのデータベースを作ったけれど、あれも使いやすかった。今のようにリレーションシップの構造を表示できない古いバージョンだったけれど、直観的な操作でそこそこ何とかなった。

http://www.filemaker.co.jp/help/html/relational.11.11.html#843565

リレーションシップグラフの操作 via kwout

先に FileMaker に馴染んだため、はじめ Access はわかりにくいなぁ~ (@_@;) と思った。 (cf. FileMaker と Access の入力フォームにおける操作モデルの違い) Access の方が VB との絡みで色々なことができるので複雑に感じたのかもしれない。しかし、今では一度 VB6 をいじった経験があるので、いざとなればクラス定義してオブジェクト生成して…と、昔よりも多少親しみを感じるようになった。

ところで、VB6 をはじめて触ったとき、Visual Studio で GUI の部品をポンポンと配置し、すぐに見かけだけでもそれなりのものができることに驚いた記憶がある。なぜなら、それまでは Java をいじっていて、はじめて買った本には Swing の説明すらなく、AWT でこつこつと完成予定の GUI の姿を想像しながらソースを書いていたからだ。そして、思ったようになかなかできないことにイライラと…。(+_+) Mac 使っていたときは、Mac OSX に付属していた開発環境の中の Interface Builder のスマートさを見て、あぁ~こんな感じに Java の環境がなったらいいのにと感じた。その頃に比べれば、今の Netbeans の GUI ビルダーはすごいなぁ。

 

目的

さて、というわけでお手軽に GUI を配置できるツールをまたいじってみたくなったので、 Visual Studio をインストールすることに。せっかくなので全く知らない C# をかじることにしよう。

DB は SQL Server をインストールし、Visual Studio + SQL Server で Access の代わりにならないかと目論む。

とりあえずの目的は、

  • C# に触れる
  • 組み込みの SQL Server をデスクトップアプリケーションで利用
  • 他の PC に SQL Server をインストールして C/S
  • ついでに余力があれば ASP.NET

.NET はやったことがないけれど、手元には何年か前に買って放置してた、

がある。中身、ASP と VB だけれど何かの参考になるかも。^^;

 

インストール

Visual Studio 2008

Visual Studio 2008 Express Editions をダウンロードしてインストール。

 

SQL Server 2008

SQL Server について調べていたら、

SQL Server 2008 の Reporting Services は無茶苦茶ヤバイです (^^
ものすごく使いやすくなって、グラフの種類が増えて、…

(SQL Server 2008 の Reporting Services は無茶苦茶スゴイ! より)

と書かれていたので、「これでレポート作成ができるのだろうか?」と思い、

ローカル リレーショナル データでの SQL Server Reporting Services レポートの実行。(ダウンロードの詳細 : Microsoft SQL Server 2008 Express with Advanced Services より)

と説明があった Microsoft® SQL Server® 2008 Express with Advanced Services をダウンロードして別途インストール。

途中、Windows PowerShell も必要だったのでインストール。

 

インストールしたもの

とりあえずインストールしたものは、データベースエンジン以外では上記「Reporting Services」と「管理ツール」。

090323-001

 

Reporting Services のアカウント

`Reporting Services’ はサービスのアカウントを指定するように求められた。Windows Service にみる別の資格情報で process を起動する安全な方法 によると、

Windows Service ですが、default では 'NT AUTHORITY\SYSTEM' で起動するように構成されるのが多いわけですが、'NT AUTHORITY\SYSTEM' 以外の account で起動できるのもご存知の方は多いでしょう。
'NT AUTHORITY\SYSTEM' は password が無い特殊な account なので例外として、その他の account で Windows Service を起動する場合、他の process を起動する場合と同様に password が必須になるわけです。

まずは動けばいいので、`NT Authority System’ を選んでおいた。

090323-002

 

インスタンスの名称

インスタンスの名称はデフォルトのままにした。

090403-001

後で知ったが、「Workgroup、Standard、Enterprise Edition へのアップグレード」 によると、

注意事項として、Express Edition の既定の名前「SQLExpress」を使用している場合、そのインスタンスをアップグレードさせることはできません。

パタッ(o_ _)o~†

 

管理者の指定

ちなみに最初インストールしたとき、「管理者の指定」するのを忘れてた。 (+_+) そのため、 SQL Server Management Studio を起動してもサーバに接続できなかった。 ^^;

認証モードは、

「Windows 認証が基本」

(http://www.sqlpassj.org/bunkakai/security/series/kihon/01.aspx より)

とあったのでそのように。

現在のユーザーの追加」ボタンを押して管理者を指定した。

090403-005 

 

SQL Server Management Studio で接続

インストールが終ったので、SQL Server Management Studio を起動。「サーバ名」を<参照>して「ローカルサーバー」のデータベースエンジンから選択して、接続できることを確認した。

 090403-006

 

Report Builder のインストールと接続

Report Builder 2.0は、Office 2007シリーズと同様のリボンインターフェースや、データベースへの選択クエリを自動生成するツールを搭載し、専門的な開発ツールやSQL言語に不慣れなユーザーでも、多次元の表形式、グラフ、チャートおよびゲージなどを含むグラフィカルなレポートのセルフサービス型による作成を可能にする。

(マイクロソフト、SQL Server 2008対応のレポート作成ツールを無償提供開始:CodeZine より)

ダウンロードの詳細 : SQL Server 2008 レポート ビルダ 2.0 よりダウンロードしてインストール。

 

後は、「SQL Server 2008 Reporting Services 入門」 を見ながら、SQL Server への接続を行なった。

まず、レポートビルダーを起動したら、レポートデータ ペインにおいて「新規 > データソース」。

レポートに埋め込まれた接続を使用する」を選択し、`Microsoft SQL Server’ を選び、「ビルド」ボタンを押す。

090406-002

 

サーバ名に「サーバ名\インスタンス名」を指定し、作成したデータベースを選択する。

090406-001