社内SEの徒然なる日記

OneNoteで書ける場所を増やしたい(スペースの挿入)

打てる場所を増やしたい

OneNoteでいろいろ書いていったのですが、もっと下の方に書く場所が欲しくなりました。
境界ギリギリの場所に文字とか打ったら、若干は場所が増えるのですが、いくらなんでも不便です。

いくらなんでも、そんな不便なわけがないと思うのだが...
OneNote(スペースの挿入1)

スペースの挿入ってのを使うらしい

調べてみると、スペースの挿入って機能を使うらしい。
まぁ、言ってることは間違ってないけど、直感的に分りずらい表現ですよね。
それとも、他の人はこの表現で分るのだろうか? ...もしや、俺がおかしいのか?

ともあれ、やってみます。
まず、挿入タグを選択して、スペースの挿入をクリックします。
(スペースの挿入は、描画タブにもあります)
OneNote(スペースの挿入2)

マウスをページ内に移動させると、マウスカーソルが矢印付の黒いのに変わって、青いバーが表示されます。
OneNote(スペースの挿入4)

ドラッグして下に引っ張ってやります。
引っ張った分だけ、書ける場所が増えます。
OneNote(スペースの挿入3)

おしまい

サンプルでは下方向に増やしましたが、右方向にも増やせます。

OneNoteとは関係ないのですが、今回一番苦労したのは、マウスが黒いカーソルになる画面のキャプチャです。
キャプチャソフトとか、Windows標準の方法(PrintScreenキー)とか、いろいろ試したのですが、どうしても黒いカーソルが消えてしまいます(青いバーのみキャプチャされる)。

しょうがないので、予備パソコンからリモートデスクトップで接続して、OneNoteの画面を表示。
予備パソコンから、リモートデスクトップの画面自体をキャプチャして画像作成。作成した画像を、メインパソコンに転送する。っていう手順を踏みました。

OneNoteを使って、効率の良い仕事の進め方を目指したのですが、なんだか余計な作業が増えてるだけのような気がしてきました。

まぁ、ブログに書くことを諦めれば済む話なんですけどね。


スポンサードリンク

PageTop

OneNoteでページのタイトルを変更する

ページタイトルが変更できない

OneNoteに新しいページを追加しました。
ここまでは分ったのですが、追加したページの名前を変更する方法が分からん。

Excelと同じように、シート名の部分を直接直せると思ったのですが、どうやらそういうものではないようです。

※ 画面右側に表示されたリリースの「無題のページ」っていうのを変更したい。
OneNote(ページタイトル変更1)

こうする(たぶん、これが正攻法)

まず、表示タグのページタイトルの非表示をクリックします。
OneNote(ページタイトル変更2)

すると、こんな枠が表示されます。ここに文字を打てば良いようです。
OneNote(ページタイトル変更3)

打ちました。
OneNote(ページタイトル変更4)

OK!変更できましたね。
OneNote(ページタイトル変更5)

ページタイトルを削除する

ちなみに、ページタイトルが設定されている状態で、もう一度、表示タグのページタイトルの非表示をクリックすると...
OneNote(ページタイトル変更2)

こんなメッセージが表示されます。ここで、「はい」をクリックすると消えます。
OneNote(ページタイトル変更6)

ほら、元どおり「無題のページ」に戻りました。
OneNote(ページタイトル変更7)

※ 注意

画面はメッセージ表示時の初期状態です。
どうやら「いいえ」がデフォルト値のようですね。
当然ですが、「このメッセージを今後表示しない」のチェックを付けてしますと、この確認メッセージは表示されなくなります。

これでもOKらしい

ページタイトルが未入力の状態で、適当な場所にテキストを打ち込むと、それがページタイトルになります。

例えば、こんな感じ。
OneNote(ページタイトル変更8)

複数のテキストがある場合は、一番左上のが優先されるみたいです。
OneNote(ページタイトル変更9)

レイアウト上、ページタイトルが邪魔な時に使える...かなぁ?
なーんか邪道な感じがします。

おしまい

どうやら、OneNoteのページタイトルってのはPowerPointと同じ概念のようですね。
まぁ、ソフトの性質を考えると、それが正しい気がします。

...それにしても、たかがタイトル付けるだけで結構疲れました。
やれやれです。

スポンサードリンク

PageTop

OneNoteでページの背景色を変更する

OneNoteを使い始めました

システム設計をするにあたって、思いついた事を片っ端から書きなぐっていくことがあります。
今までは、紙に書くか、Excelで何とかしていたんですが、これが具合よくない。

何度も消して、書いてを繰り返すので、紙だと面倒。
かといって、Excelだと書きにくい(そういうものじゃないから当然ですが)。

そんな時、ふとOneNoteなるものがあったのを思い出して使ってみたところ、意外と具合がいいです。
とはいえ、初めて使うソフトなので使い方に四苦八苦です。

とりあえず、ふと思い悩むことがあったら、どんどん備忘録(このブログ)に書いていく事にします。

ページの背景色を変える

OneNoteを初めて起動して使い始めたページの背景色は、黄色っぽい色だったのですが、新しいページを追加したところ、背景色が白になっていました。

...まぁ、白のままでも良いんですけど、なんか寂しいので変更します。

表示タグから、ページの色をクリック、表示されるメニューから好きな色をクリックすればOKです。
OneNote(背景色を変える)

後記

私の環境は、WindowsXP SP3で、OneNote2010です。
今回の背景色の変更方法も、わかってしまえば簡単でしたが、見つけるまで時間がかかりました。
この有様では、先が思いやられますね。
スポンサードリンク

PageTop

SQLテクニック(行ロック:FOR UPDATE)

検索実行時にテーブルをロックしたい

1つのトランザクションの中で、検索(SELECT文)を発行した時に、ロックをしたいことがあるかと思います。
というか、必要が生じました。

とある処理で、数値が不整合を起こす障害の原因調査をしたのですが、これが酷い。
処理自体は、あるテーブルの金額項目に対して、ユーザーが画面から入力した数値を加算するっていうものです。
仕様書に書いてるのは、こんな内容。

1.SELECT文でテーブルAからデータ抽出
2.1で取得した金額に、画面で入力した金額を加算
3.2の結果をテーブルAに上書きする。


1で取得した数値を加工して上書きするって仕様なんですから、SELECT文を発行する時にロックをかけないといけません。
しかし、この処理を実装したプログラマは違う考えがあったらしく、ロックを掛けなかったようです。

...おい、ふざけるなよ。

行ロック

というわけで、SELECT文の発行と同時に行ロックを実行します。

SELECT文の最後に「FOR UPDATE」と追加すれば、検索される行がロック(悲観的ロック)されます。
このロックは、COMMIT or ROLLBACK された時点で解除されます。


SELECT
A.支店コード,
B.取引先名
FROM
与信マスタ A,
取引先マスタ B
WHERE
A.取引先コード = B.取引先コード
FOR UPDATE


このサンプルでは、「与信マスタ」と「取引先マスタ」がロックされます。

対象テーブルを指定した行ロック

テーブルを結合して対象データを絞りこんでいる時に「FOR UPDATE OF テーブル名.項目名」とすることでどのテーブル(の行)をロックするか設定できます。

下記のサンプルでは項目名まで指定していますが、あくまでも対象となるテーブル(の行)を指定するためのものなので指定した項目だけロックされる(されない)というものではありません。


SELECT
A.支店コード,
B.取引先名
FROM
与信マスタ A,
取引先マスタ B
WHERE
A.取引先コード = B.取引先コード
FOR UPDATE OF A.支店コード


「FOR UPDATE OF A.支店コード, B.支店コード」とカンマで区切れば取引先マスタもロックされます。

ロックが解除されるタイミング

FOR UPDATE によるロックは、COMMIT or ROLLBACK が発行された時点で解除されます。
つまり、トランザクションが終了した時ってことですね。

余談

UPDATE文やDELETE文の場合は、特に何もせずともロックされます。
当然、これもCOMMIT or ROLLBACK が実行された時点で解除されます。

...障害発生時の条件だと、別にSELECT文でデータ抽出なんかせずに、UPDATE文で加算してやれば良かったんじゃないかと思います。
まぁ、今さらですがね。
スポンサードリンク

PageTop

Excelでシート保護した状態でオートフィルタを使用する

オートフィルタ

同僚に、Excelでシート保護をした状態でオートフィルタを使用する方法を聞かれました。

使っているExcelのバージョンは2010なので、「シート保護する時のオプションに、オートフィルタを許可する設定があったと思いますけど」て返したのですが、「Excel2000でも使えるようにしたい」ということ。

たしかExcel2000だと、シート保護した状態でExcelを終了すると、再度立ち上げた時にオートフィルタが使用できなくなったはず。これは、マクロで何とか出来たはずだが...。

とりあえず、試して見ました。

テストデータの作成

とりあえず、テスト用にこんな表を準備します。
Excelフィルタ(表)

表の中を選択して...
Excelフィルタ(フィルタ設定1)

オートフィルタを設定します。
Excelフィルタ(フィルタ設定2)

さて...

Excel2010の場合

まずは、Excel2010の機能で対応してみます。
このVerなら、小細工はいらなかったはず。

まず、校閲タグからシート保護を選択します。
Excelフィルタ(シート保護1)

リストの下の方にある、オートフィルターの使用にチェックを付けて、OKボタンをクリックします。
Excelフィルタ(シート保護2)

これで、シート保護された状態で、オートフィルターを使用できるようになりました。
もちろん、ブックを再立ち上げしてもオートフィルターは使用できるままです。
Excelフィルタ(使用)

Excel2000の場合

さて、今度はExcel2000での対応方法です。
こちらは、マクロで小細工する必要があったはず。

テストデータは、同じ表を使用します。
私の端末、Excel2000がインストールされていないので、操作画面はExcel2010になっています。

まず、開発タグからVisual Basicを起動します。
Excelフィルタ(コード表示)

左側のリスト(プロジェクトエクスプローラ)から、ThisWorkbookを右クリックして、コードの表示をクリックします。
※ ThisWorkbookをダブルクリックしてもOKです。
Excelフィルタ(ThisWorkbook)

コード編集画面が表示されるので、左上のリストからWorkbookを選択します。
Excelフィルタ(WorkbookOpen1)

すると、こんなメソッドが作られるはずです。
この、Workbook_Openってのは、Excel起動時に自動実行されるマクロです。
ここに、小細工に必要な処理を突っ込みます。
Excelフィルタ(WorkbookOpen2)

突っ込みました。

'Excel起動時の処理
Private Sub Workbook_Open()

'シート保護時のオートフィルタを使用可
Sheet1.EnableAutoFilter = True

'シート保護
Sheet1.Protect UserInterfaceOnly:=True

End Sub


ソース解説

まず、フィルタをかけたいシートの、EnableAutoFilterプロパティにTrueを設定します。
これによって「画面上からの変更のみの保護を設定している時に、ワークシートのオートフィルター矢印を使用可能にする」ことが出来ます。

画面上からの変更云々というのは、「ユーザーからの操作は保護するが、マクロからの操作は許可する」という、シート保護(Protectメソッド)の設定のことです。
これは、Protectメソッドのパラメータ「UserInterfaceOnly」にTrueを設定することで可能になります。

この処理を、Workbook_Openメソッドに書くのは、EnableAutoFilterプロパティの設定が、Excelを終了すると消えてしまうので、Excel起動時に自動実行させることで、常にこのプロパティがTrueになるようにしています。

余談

Excel起動時の自動実行といえば、Workbook_Openメソッドの他にAuto_Openメソッドでも可能です。
...ですが、私は最近はAuto_Openメソッド使用していません。

Workbook_Openメソッドを使った方がスマートだと(個人的には)思っているのが最大の理由ですが、Excel2000以降のバージョンでAuto_Openメソッドが安定動作しないことが頻発したからです。

個人的な拘りといわれそうですが、妙な個所で止まったり、コンパイルエラーが発生したりする事象が頻発する現実を考えると、怖くて使えません。

スポンサードリンク

PageTop

NetCOBOLのソース編集をExcelマクロで作ってみた(実行結果)

初めに

※ 本記事は、ExcelマクロでCOBOLソースを自動編集させるマクロを作る記事の第5話(最終話)です。

準備

シート上にボタンを設置して、ここに前回(NetCOBOLのソース編集をExcelマクロで作ってみた(Cobolソース編集))作成したSourceEditメソッドを登録します。
COBOLソース編集(シート)

このボタンを押すと、処理が実行されます。

一連番号領域の編集

一連番号領域に、あり得ない値を設定したソースを準備します。
5行目には、空白行を作っておきます。
NetCOBOL(連続番号領域前)

下記は、処理実行後の結果です。
一連番号領域にあった不正値が連番に上書きされ、5行目の空白行が削除されています。
NetCOBOL(連続番号領域後)

SQL領域の編集

今度は、EXEC SQL ~ END-EXEC. の範囲内の編集が動作するか見て見ます。
埋込みSQLの範囲内に、COBOLの行内コメントを書いておきます。
NetCOBOL(EXECSQL前)

実行結果です(一連番号領域を空白にするモードで実行)。
COBOLの行内コメントが、80BYTEから始まるように移動されています。
NetCOBOL(EXECSQL後)

上手く行ったね

どうやら、上手く動いてくれました。
サンプルには提示していませんが、後方空白の除去機能もきちんと動作してくれます。

第1話(概要): NetCOBOLのソース編集をExcelマクロで作ってみた(概要)
第2話(共通関数): NetCOBOLのソース編集をExcelマクロで作ってみた(共通関数)
第3話(専用関数): NetCOBOLのソース編集をExcelマクロで作ってみた(専用関数)
第4話(Cobolソース編集) : NetCOBOLのソース編集をExcelマクロで作ってみた(Cobolソース編集)
第5話(実行結果) : この記事です

投稿記事の一覧:目次

※ 追記1 動作環境

確認した動作環境は、WindowsXP SP3、Excel2000とExcel2010で動作確認しています。

※ 追記2 サンプルで使用したエディタ

今回の実行結果のサンプル表示に使用したのは、DeuxEditorというフリーのテキストエディタです。
短形選択、強調表示、文字コード・改行コードの指定などを備えた、タブ型の高機能テキストエディタです。

NetCOBOLで開発を始めた時から、ずっとエディタを探していたのですが、いろいろ試した結果こいつに落ち着きました。

※ 追記3 一連番号領域

資産管理をsubVersionで行っているのですが、一連番号領域を採番しなおすと、subVersionで変更履歴が参照できなくなってしまって不便だったので、いっそのこと全部空白にするモードを作成しました。
スポンサードリンク

PageTop

自力で寿司を作ってみた

寿司、うまー

先日食べた銀のさらの寿司(銀のさら(宅配寿司)を試してみた)が美味しかった。
もう一度食べたいのですが、さすがにまずい(エンゲル係数的に)ので、自力で作る事にしました。

作ってみた

まず、圧力鍋で普通にご飯を炊きます。

ご飯が炊けたら、市販のすし酢を振りかけます。
使用する酢は、ミツカンのすし酢(昆布だし入り)です。
酢飯を作るなら、これが一番良いらしいです。
すし酢

ネタは、適当に数種類用意して、さらに適当にご飯の上にのせます。
うまく握れないので、のりを巻いて無理矢理軍艦巻きにしてやりました。

自作の寿司

適当に作った割には見れる形に・・・
なってるかなぁ?

まぁ、どうせ自分で食べるだけなので、見栄えはどうでも良いんですけどね。
ちなみに、左上の軍艦の上に乗っているのは、チューブショウガです。

食べてみた

食べました。
味は・・・・・・・・・・・・・・・・・・いやぁ、プロって凄いですね。

やってることは、酢飯の上にネタを乗っけるだけなんですけど、素人には理解できない技術があるんでしょうね。
それでも、不味いってほどでもなかったので、全部頂きました。

酢飯とネタが結構残ったので、こちらは握らずに生チラシにしました。
手間ひま掛けて握るより、よっぽど美味しいのはどうかと思いましたけどね。

余談ですが、ご飯焚くのに炊飯器を使わないのは、単純に持っていないからです。
家に不要な物を置きたくない性格なので、代用できる圧力鍋でご飯炊いているのですよ。
スポンサードリンク

PageTop

銀のさら(宅配寿司)を試してみた

銀のさら

最近、銀のさらの宅配メニューが手に入ったので、頼んでみる事にしました。
折角なので、感想でも書いとく事にします。

...トロサーモンなるものがとても気になる。

注文はwebから出来るようです。
ショッピング系のサイトとほぼ同じイメージですね。

注文システムは、注文すると登録したメールアドレスに注文確認メールが送信されて、そのメール内のリンクをクリックする事で注文が確定する仕組みのようです。

結局、メールが必要になる訳ですから、最初にwebの会員登録をしておいたほうが良さそうですね。
注文画面では、即時宅配の依頼の他に、予約も可能なようです。
まぁ、今回は直ぐに配達してもらいます。

到着

web画面によると、配達までに約70分とのことなので、先に風呂につかる事にしました。
んで、上がって一休みしている時に、知らない番号からの電話が鳴り響きます。
何かと思ったら、寿司が出来て、これから配達するとのこと(意外に早かった)。

わざわざ電話確認?
...ふーむ、成り済ましとかの対策なんだろうか?

ちなみに支払いは、いつもニコニコ現金払いのみだそうです。

商品

紅葉(もみじ)の一人前です。
銀の皿(紅葉)

web画面で容器を選択できたので、使い捨てパックを選択しました。
特に料金が変わる訳ではないので、どちらでも良かったんですけどね。

こちらは、トロサーモンです。
銀の皿(トロサーモン)

現在の小銭の手持ちだと、↑だけでは結構なおつりがでるので、単品でトロサーモンを追加して金額調整しました。

注文した寿司以外では、割り箸、醤油、お吸い物が付いてきました。
銀の皿(添付)

メニュー内に、みそ汁が見当たらなくて不思議だったのですが、お吸い物がサービスになっているのでみそ汁は不要という判断のようです。

もう一つ、ポイントカードも持ってきました。
銀の皿(ポイントカード)

3,000円で1ポイントで、15ポイントで3,000円の割引券になるようです。

食べてみた

食事直前の光景です。
銀の皿(全景)

添付のお吸い物、醤油皿は容器のフタを使用、コップに入っているのは日本酒(越後桜)です。
実は、納豆巻きも頼んでいました。

肝心の味の方ですが、思ったよりはずっと美味しいです。
ネタには厚みがあり、ご飯は水分すくなめでクセがない感じ。
正直、あまり期待していなかったので、良い意味で裏切られました。

トロサーモン、マグロの中トロ、ウニ、口の中で溶けて最高です。

まぁ、めちゃくちゃ美味しいとは言いませんが、少なくても値段相応の味といって良いのではないでしょうか。

総評

全体的には、「良」の評価でした。
値段、配達時間、配達の兄ちゃんの態度、概ね悪くはないです。

出来れば、添付のお吸い物をみそ汁に変更できれば良かったかなと。
あと、不思議だったのは、ドリンクの注文が150mlのペットボトルだけということです。
旅行とかで見かける、水を入れてヒモを引くと温かくなるヤツとか、温かいお茶があっても良かったかなと。

それと、お酒は置けないんでしょうかね?
日本酒、ビールを飲みながら寿司を食べるのって結構好きなんですけどね。
宅配ピザにも酒はなかったと思うので、法令の縛りでもあるのでしょうか?

後は、ポイントカードですか。
なかなか良心的なポイントサービスだと思うのですが、私のような独り身だと、1回の注文が3,000円を超える事がほとんどなさそう。
これでは、ポイントが溜まりそうにないですね。

折角のwebシステムなのだから、累計注文金額でポイント発行とかしてくれれば嬉しいんですけどね。

結構文句も書きましたが、概ね好評価です。
また、気が向いた時に頼むことにします。

スポンサードリンク

PageTop

NetCOBOLのソース編集をExcelマクロで作ってみた(Cobolソース編集)

初めに

※ 本記事は、ExcelマクロでCOBOLソースを自動編集させるマクロを作る記事の第4話です。

メインロジック

今回は、OrthographyEditモジュールです。
このモジュール内のSourceEditメソッドを実行することで、ソース編集を実行します。


Option Explicit

'表示用に使用するエディタを定義する。 既定値はメモ帳
'Private Const COB_EDITER As String = "notepad "
Private Const COB_EDITER As String = "D:\Program Files\Yokka\DeuxEditor\DeuxEditor.exe "

'ファイルシステムオブジェクト
Private Const ForReading As Integer = 1 '読み取り専用でファイルを開きます。このファイルに書き込むことはできません。
Private Const ForAppending As Integer = 8 'ファイルを開き、ファイルの末尾から書き込みます。
Private Const TristateUseDefault As Double = -2 'システムの既定値を使ってファイルを開きます。
Private Const TristateTrue As Double = -1 'Unicode としてファイルを開きます。
Private Const TristateFalse As Double = 0 'ASCII ファイルとしてファイルを開きます。


' 機能 : COBOLソース編集
'
' 機能説明 : COBOLソースファイルを読み込んで自動編集します。
' : 1. 一連番号領域の番号を更新する
' : 2. 右側空白を除去する
' : 3. 空白行があった場合コメント行とする
'

Public Sub SourceEdit()

'-----------
' 変数宣言
'-----------


'FileSystemObject
Dim fso As Object '
Dim myInFile As Object 'ソースファイル
Dim myOutFile As Object '出力ファイル

'ファイル情報
Dim myFolder As String
Dim myFile As String
Dim myPath '編集対象Sourceパス

'ソースコード
Dim myWorkStr As String '読み込みテキスト行
Dim myWriteStr As String '書き込みテキスト

'編集用
Dim myNo As String '連番
Dim myByte As Integer '行のバイト数
Dim myNoDom As String '一連番号領域
Dim myABDom As String 'cobolソースA領域・B領域
Dim mySqlComNum As Integer 'SQL文中のコメント開始位置

'フラグ
Dim myNoSpaceFlg As Boolean '一連番号領域フラグ(true:空白にする、false:連番で上書きする)
Dim myExecSql As Boolean 'EXEC SQL 文中の処理か判断フラグ(True:SQL中, False:SQL中でない)

'Shell関数の戻値
Dim myRetVal As Variant

'------------
' 初期処理
'------------


'フラグのクリア
myExecSql = False 'SQL中フラグ

'一連番号領域の扱い選択
Select Case MsgBox("一連番号領域の扱いはどうしますか?" & Chr(10) & Chr(10) & _
" 空白 : はい" & Chr(10) & _
" 連番 : いいえ" _
, vbYesNoCancel)

Case vbYes: myNoSpaceFlg = True
Case vbNo: myNoSpaceFlg = False
Case vbCancel: Exit Sub
Case Else:
MsgBox "一連番号領域の扱い選択のシステムエラー"
Exit Sub
End Select

'COBOLソースの選択
myPath = Application.GetOpenFilename("COBOLソース(*.cob;*.pco;*.CBL),*.cob;*.pco;*.CBL", , "COBOLソース選択")
If myPath = False Then
Exit Sub
End If

'--------------
' ファイル生成
'--------------


'ファイル生成用のオブジェクト作成
Set fso = CreateObject("Scripting.FileSystemObject")

'cobolソースのopen
Set myInFile = fso.OpenTextFile(myPath, ForReading, True, TristateFalse)

'tmpの作成
myFolder = fso.GetSpecialFolder(2)
myFile = fso.GetTempName
fso.CreateTextFile (myFolder & "\" & myFile)
Set myOutFile = fso.OpenTextFile(myFolder & "\" & myFile, ForAppending, False, TristateFalse)

'--------------
' 編集開始
'--------------


'cobolソースの編集
Do While myInFile.AtEndOfStream <> True

'1行読み込みます。
myWorkStr = myInFile.ReadLine

'実体のない行は、無視します。
If Trim(myWorkStr) <> "" Then

'右側空白の除去
myWriteStr = RTrim(myWorkStr)

'一連番号領域の更新
myByte = K_LenByte(myWriteStr)

'Byte数が6以上の場合
If myByte >= 6 Then

'-------------
' 領域情報取得
'-------------


'一連番号領域を取得
myNoDom = K_midByte(myWorkStr, 1, 6)

'AB領域を取得
myABDom = K_midByte(myWorkStr, 7, myByte - 6)

'標識領域に全角文字がある時は、AB領域を1Byte右にシフトする
If K_LenByte(K_midByte(myWorkStr, 7, 1)) = 2 Then
myABDom = " " & myABDom
Debug.Print "行№ - " & myInFile.Line - 1 & " 「異常」標識領域にまたがる形で全角文字があります(警告)"
End If

'標識領域に全角文字がある場合は空白に置き換える
If K_LenByte(myNoDom) <> 6 Then
Debug.Print "行№ - " & myInFile.Line - 1 & " 「異常」標識領域にまたがる形で全角文字があります"
myNoDom = ""
End If

'------------
' SQL文編集
'------------


'SQL使用の判断
If myExecSql = False Then
myExecSql = ExecSqlStartChk(myNoDom & myABDom)
End If

'SQL文中の場合、単一行コメント判定
If myExecSql = True Then

'単一行コメントが存在する
mySqlComNum = InStr(1, myABDom, "*>")
If mySqlComNum > 0 Then

'単一行コメントの位置が74Byte以降の場合
If mySqlComNum > 74 Then
'コメントの位置を、75Byteから始まるように調整する
myABDom = Left(myABDom, 74) & Right(myABDom, Len(myABDom) - mySqlComNum + 1)

'単一行コメントが74Byte以前の場合
Else
'コメントの位置を、75Byteから始まるように調整する
myABDom = Left(myABDom, mySqlComNum - 1) & _
String(74 - (mySqlComNum - 1), " ") & _
Right(myABDom, Len(myABDom) - mySqlComNum + 1)
End If
End If
End If

'SQL使用終了の判断
If myExecSql = True Then
If ExecSqlEndChk(myNoDom & myABDom) = True Then
myExecSql = False
End If
End If

'--------------
' ファイル出力
'--------------


'一連番号領域が数値のみ、又は空白の場合
If IsNumeric(myNoDom) Or Trim(myNoDom) = "" Then
'通常出力
If myABDom = "" Then
myWriteStr = cobolNoAdd(myNo, myNoSpaceFlg) & "*"
Else
myWriteStr = cobolNoAdd(myNo, myNoSpaceFlg) & myABDom
End If
myOutFile.WriteLine myWriteStr

'一連番号領域に数値、空白以外の文字がある場合
Else
'一連番号領域の現在値を強制的に上書きします。
Debug.Print "行№ - " & myInFile.Line - 1 & " 「警告」一連番号領域に不正文字【" & myNoDom & "】 領域番号を上書きしました"
myWriteStr = cobolNoAdd(myNo, myNoSpaceFlg) & myABDom
myOutFile.WriteLine myWriteStr
End If

'5byte以下の場合、強制的にコメント行にする
Else
'一連番号領域の現在値を強制的に上書きします。
Debug.Print "行№ - " & myInFile.Line - 1 & " 「警告」一連番号領域に不正文字【" & myWorkStr & "】 領域番号を上書きしました"
myWriteStr = cobolNoAdd(myNo, myNoSpaceFlg) & "*"
myOutFile.WriteLine myWriteStr
End If

End If

Loop

'----------
'終了処理
'----------

normalEnd:

'編集した結果でオリジナルを上書きします。
fso.CopyFile myFolder & "\" & myFile, myPath, True

'編集したソースを表示します。
myRetVal = Shell(COB_EDITER & myPath, vbNormalFocus)

'入出力ファイルを閉じる
myInFile.Close '入力ファイル
myOutFile.Close '出力ファイル

'出力ファイルを削除する
fso.DeleteFile (myFolder & "\" & myFile)

'FileSystemObjectの開放
Set fso = Nothing
Set myInFile = Nothing
Set myOutFile = Nothing

Exit Sub

End Sub


ファイルシステムオブジェクトを使用して、選択されたテキストファイル(COBOLソースファイル)に対して編集を行います。
編集内容については、第1話で記述した内容です。
編集といっても、直接ファイルを編集するのではなくて、ソース編集用のワークファイルを作成して、最後に元のファイルを上書きするという手順を使っています。

編集後、対象ファイルをテキストエディタでOPENします。
このとき使用するエディタは、Public変数「COB_EDITER」で指定します。

欠点があるとすれば、この処理を通す前のオリジナルのソースが残らないってことですかね。
まぁ、その手の管理は資産管理ソフトで行うものと割り切っています。

第1話(概要): NetCOBOLのソース編集をExcelマクロで作ってみた(概要)
第2話(共通関数): NetCOBOLのソース編集をExcelマクロで作ってみた(共通関数)
第3話(専用関数): NetCOBOLのソース編集をExcelマクロで作ってみた(専用関数)
第4話(Cobolソース編集) : この記事です
第5話(実行結果) : NetCOBOLのソース編集をExcelマクロで作ってみた(実行結果)

投稿記事の一覧:目次

次回

次回は、完成したマクロを動かして見ます。

スポンサードリンク

PageTop

NetCOBOLのソース編集をExcelマクロで作ってみた(専用関数)

初めに

※ 本記事は、ExcelマクロでCOBOLソースを自動編集させるマクロを作る記事の第3話です。

専用関数

今回は、commonLocalモジュールを作成します。

まず、SQL節の開始と終了を判断する必要があります。
なので、開始と終了を判断する関数を用意します。

これが、開始を判断する関数です。
いろいろとやっていますが、要するに「EXEC SQL」であればTrueを返却しています。

' 機能 : COBOLソース解析(SQL宣言の開始判定)
'
' 返り値 : TRUE - SQL宣言開始 , FALSE - SQL宣言では無い
'
' 引き数 : pLine - 判定する行(文字列)
'
' 機能説明 : 引数として受け取ったコードがSQL宣言の開始(EXEC SQL)をしているかを取得する関数
'
' 備考 :
'

Public Function ExecSqlStartChk(ByVal pLine As String) As Boolean

Dim myLen As Integer
Dim myNum As Integer
Dim myWorkStr As String

myLen = Len(RTrim(pLine))

'規定桁数以下
If myLen < 16 Then
GoTo falseEnd
End If

'コメント行判断
If Mid(pLine, 7, 1) = "*" Then
GoTo falseEnd
End If

If InStr(1, pLine, " EXEC ") > 0 _
And InStr(1, pLine, " SQL") > 0 _
And InStr(1, pLine, " EXEC ") < InStr(1, pLine, " SQL") Then

'EXEC の 次は SQL がある
myWorkStr = Mid(pLine, InStr(1, pLine, " EXEC ") + 5, (InStr(1, pLine, " SQL") + 1) - (InStr(1, pLine, " EXEC ") + 5))
If Trim(myWorkStr) <> "" Then
GoTo falseEnd
End If

'単一コメント行制御
If InStr(1, pLine, "*>") > 0 _
And InStr(1, pLine, "*>") < InStr(1, Trim(pLine), "EXECSQL") Then
GoTo falseEnd
End If

myNum = InStr(1, pLine, " SQL")
If myLen > myNum + 3 Then
If Mid(pLine, myNum + 4, 1) = " " Then
GoTo trueEnd
Else
GoTo falseEnd
End If
Else
GoTo trueEnd
End If
End If

GoTo falseEnd

trueEnd:
ExecSqlStartChk = True
Exit Function
falseEnd:
ExecSqlStartChk = False
Exit Function
End Function


上記の、ExecSqlStartChk関数の対になる関数です。
SQL節の終了、つまり「END-EXEC」であれば、Trueを返す関数です。

' 機能 : COBOLソース解析(SQL宣言の終了)
'
' 返り値 : TRUE - SQL宣言終了 , FALSE - SQL宣言終了ではない
'
' 引き数 : pLine - 判定する行(文字列)
'
' 機能説明 : 引数として受け取ったコードがSQL宣言の終了(END-EXEC)をしているかを取得する関数
' :
' : ①コード中に END-EXECが存在する場合はTrue(END-EXECの前には1文字の半角スペースがある)
' : ② ①の例外として、END-EXECが7文字(連続番号領域・標識領域)にかかっている場合はFalse
' : ③ ①の例外として、END-EXECの後は空白、.(ピリオド)、*>(単一行コメント)以外の場合はFalse
' : ④ 対象行がコメント行、又は単一コメント宣言移行の場合はFalse
'
' 備考 :
'

Public Function ExecSqlEndChk(ByVal pLine As String) As Boolean

Dim myLen As Integer
Dim myNum As Integer

myLen = Len(RTrim(pLine))

myNum = InStr(1, pLine, " END-EXEC")

If myNum > 6 And myLen >= 16 Then
If Mid(pLine, 7, 1) = "*" Then
ExecSqlEndChk = False
Else
If InStr(1, pLine, "*>") > 0 And InStr(1, pLine, "*>") < myNum Then
ExecSqlEndChk = False
Else
If myLen > myNum + 8 Then
If Mid(pLine, myNum + 9, 1) = "." Then
ExecSqlEndChk = True
Else
If Mid(pLine, myNum + 9, 2) = "*>" Then
ExecSqlEndChk = True
Else
ExecSqlEndChk = False
End If
End If
Else
ExecSqlEndChk = True
End If
End If
End If
Else
ExecSqlEndChk = False
End If

End Function


もうひとつ、関数を準備します。
COBOLの特徴のひとつである連続番号領域の値を生成する関数です。
基本機能としては単純で、引数で受けた値に10を加算しているだけです。
ただし、連番を使用しないパターンにも対応させています。

' 機能 : COBOLソース用の連番生成
'
' 返り値 : 引数で与えられた連番に10を加算した値。
' : 6桁になるように先頭に0埋めして返却される。
' : ただし、引数「pNoSpaceFlg」がTrueの場合、6桁のスペースを返却する。
'
' 引き数 : pNo - 連番の現在地
' : pNoSpaceFlg - True:連番を生成しない、False:連番を生成する
'
' 機能説明 : 引数として連番に10を加算した値を返します。
'
' 備考 :
'

Public Function cobolNoAdd(ByRef pNo As String, ByRef pNoSpaceFlg As Boolean) As String

'連番を設定しない場合は、空白を返却
If pNoSpaceFlg Then
cobolNoAdd = " "
Exit Function
End If

'計算用の変数
Dim myNo As Long

'未設定の場合は0で補正
If pNo = "" Then
pNo = "000000"
End If

'長整数方に変換して 10 を加算
myNo = CLng(pNo)
myNo = myNo + 10

'6桁になるように先頭0埋めして返却
pNo = String(6 - Len(CStr(myNo)), "0") & CStr(myNo)
cobolNoAdd = pNo

End Function


第1話(概要): NetCOBOLのソース編集をExcelマクロで作ってみた(概要)
第2話(共通関数): NetCOBOLのソース編集をExcelマクロで作ってみた(共通関数)
第3話(専用関数): この記事です
第4話(Cobolソース編集) : NetCOBOLのソース編集をExcelマクロで作ってみた(Cobolソース編集)
第5話(実行結果) : NetCOBOLのソース編集をExcelマクロで作ってみた(実行結果)

投稿記事の一覧:目次

次回

次回は、いよいよ本命のOrthographyEditメソッドです。

元々が自分のためだけに作ったマクロなのでしかたないのですが、ところどころに、褒められたものじゃない書き方がありますね。
ExecSqlEndChkなんかは、ロジック中にコメントがひとつもないし。

まぁ、難しいことはしていない(つもり)ので、追えるとは思いますけどね。
スポンサードリンク

PageTop

サビやカビに強いメガネとオーバーグラス

メガネの購入

まだ、夏の日差しが強い時にメガネを買い替えました。

20歳を超えた頃から、視力の低下自体は下げ止まった感じなので、レンズ自体は良かったのですが、フレームがマズい事になっていました。

私は結構な汗かきなので、当然メガネのフレームにも汗が付きます。
寝る時以外は、常にメガネを装着するタイプなので、雨風にもあたります。
その状態で5〜6年ほど使っていたのですが、ふと気付くと、フレームの耳にあたる部分に緑色の何か(カビ?サビ?)が付いている。メガネ屋さんに持っていて相談すると、変色した部分を削って、耳にあたる部分のカバー(何て名称か分からん)を交換してくれたんですけど、傷が残って格好わるい。

ボーナスも出るので、思い切って買い替えることにしました。

パリミキで購入

メガネ屋は無数にあるのですが、今回はパリミキに行ってみました。
贔屓のメガネ屋がある訳じゃないので、近所(歩いて行ける範囲)にあるって理由です。

店員さんにダメ元で「レンズが大きくて、汗に強く、サビない、カビないメガネが欲しい」と伝えたところ、出てきたのがこれです。

メガネ(チタンフレーム)

フレームの耳にあたる部分の拡大です。
メガネのフレーム拡大

耳当て(っていうんですかね?)が無いタイプです。
所謂、チタンフレームってのらしいですが、シンプルなデザインが気に入りました。

※ エンジニアの端くれの為か、元々の性格なのか「シンプル イズ ベスト」って言葉が大好きです。

ちなみに、レンズを大きくして欲しかったのは、以前に小さなレンズに交換したところ、足下が視野に入らなくなって躓くことが多くなったからです。

耳にあたる部分が金属のためか、風呂上がりに掛けるとずり落ちるような違和感を感じていたんですが、2週間もしたころには完全に慣れてしまいました。
シンプルな外観に、大きめのレンズ、久しぶりに納得いくメガネが手に入りました。
サビとかについては、数年後に結果が分かるでしょうから、楽しみです。

オーバーグラス

秋になってから、自転車で走っていると冷たい風が目に入って涙がでるようになってきました。
なんとかならんだろうか?と思っていたところ、数日後のスケジュールに「メガネ定期点検」を発見。
すっかり忘れていたのですが、メガネを購入した時に、お客様カードなるものを渡されて、「3ヶ月後に点検にいらして下さい」と言われていたんですね。

タイミングも良かったので、行ってみました。
んで、対応してくれた店員さんに「風とか入らない、メガネの上に掛けるメガネってない?」と聞いたんですが、残念ながら「商品自体はあるのだが、あまり数が出る物ではないので店頭には置いてなく、取り寄せになる」とのことだったので、その日は諦めたのですが、後日、特別招待とかいうハガキが来て、その文面には「オーバーグラスも見れます」なる記述がある。
...え、取り寄せてくれたの?というか、オーバーグラスって名前だったの?とかいろいろ疑問はあったのですが、せっかくなので、また行ってみました。

んで、出てきたのがこれ。
株式会社アックス製の偏光レンズ(SG-605P SM)で、風や雪、紫外線などから目を保護してくれる物らしいです。
オーバーグラス

お値段が8,000円ちょっとするし、時期も冬で使う機会が少なくなるので迷ったのですが、せっかくなので購入することにしました。

※ 店員さんの、こういう地道な努力が売上げに繋がって行くんですねぇ。

使ってみた

すでに雪が降っているので、肝心の自転車(クロスバイク)での試運転は断念。
冬期間は40分位かけての徒歩通勤なので、通勤時に使ってみました。

分かったのは、若干、横風が入っちゃうくらい。やっぱり、スポーツ中に使用しないと、真価は分からないようです。
というわけで、来年の春のお楽しみですね。

ちなみに、通勤中の私の姿を見かけた同僚には、「そのマトリックスみたいなのは何だ?」とか言われました。
...いや、まぁ、うん、言いたい事は分かるよ。


スポンサードリンク

PageTop

加湿器を買いました(2012年)

加湿器を購入しました。

冬になったので、最近は空気の乾燥が酷いです。
昨日の夜も、喉が乾いて目を覚ましましたしね。

という訳で、加湿器を購入しました。
アイリスオーヤマ、efeel、SHM-100Tです。
加湿器(箱)

選定基準

購入したのはホーマック。
まぁ、実はグッピー用のカルキ抜きを買いに行った時に目についたので、ついでに買ったんですけどね。

箱の右上に「卓上タイプ」と書いている通り、かなり小さめのタイプです。
カタログスペックだけでいうと、我が家を潤すには性能が足りないのですが、贅沢を言わなければこの程度で十分要が足ります。

動かしてみた

水を入れて、スイッチオン。
加湿器(設置)

蒸気が上がってきました。バッチリですね。
加湿器(煙)

アロマオイルを垂らしておく穴もあったので、5〜6滴垂らしておきました。
ちなみに、オイルは以前に「水で空気を洗浄する」とかいう空気清浄機を買った時についてきたものの余りを使いました。

ちなみに、この空気清浄機はすでに廃棄しています。
...いや、機器の一部にカビが生えたんですよ。しかも、分解清掃が難しい場所に。
もう、捨てるしかないじゃないですか。

え?薬品とかで落ちる?
...いや、そんな面倒で費用がかかる事するくらいなら、買い直した方が早いよ。

リセットボタン

電源スイッチとは別の場所に、リセットボタンなる物を発見しました。
加湿器(リセット)

どうやら、タンクの水が無くなった時に、水を補充して、このリセットボタンを押すと運転を再開してくれるらしいです。
いや、自動で判定するか、いっそのことユーザーに電源ON/OFFさせた方がシンプルで良いと思うんですけどねぇ。

...どうせリセットボタンをつけるなら、人生リセットボタンが欲しい。

余談

私、加湿器は毎年買い替える事にしています。
というのも、使うのは冬の間だけで、それ以外の時期は押し入れの邪魔者でしかないからです。
家が狭いってのもあるんですけど、それ以上に使わないモノが増えるのが嫌でしょうがないんですよ。

どうせフィルター交換したり、何やらで費用や手間が発生するのなら、買い直した方が楽です。
という訳で、冬に購入、春にリサイクルショップに売却、冬に再購入、ってことをしています。

スポンサードリンク

PageTop

秋の終わりの白石サイクリングロード

自転車で紅葉を見に行きたい

10月(2012年)に入ってから、自転車(クロスバイク)で紅葉を見に行きたいと思って機を伺っていたのですが、今年は、休日になるたびに天気が悪くなって、結局時期を逃していしまいました。

ようやく晴れたのは、11月10日。
さすがに、紅葉は終わってますよね。

とはいえ、元々サイクリングはダイエットも兼ねているので、出かけてみる事にしました。

白石サイクリングロード

通勤途中に白石サイクリングロードを通ったところ、平野部ではまだ葉が枯れずに、紅葉が見れるようです。
あまり遠出もしたくなかったので、今回はこちらを通る事にしました。

とある橋を下から見上げた場面です。
ここ数日、雨が続いたせいか葉がすくないようですが、結構奇麗ですね。
IMG_0786.jpg

今度は、公園横と木です。
立派な黄色ですね。
IMG_0788.jpg

他にも結構撮ったんですけど、人が映っている写真を載せるのも良くないかと思ったので自粛です。

山道に侵入

さて、そうこうしている内に、山道に侵入して行きます。
さすがに、この辺りではすでに紅葉は終わって枯山になっています。

IMG_0809.jpg

寄り道(トンボ発見)

このサイクリングロードには、途中に歩いて侵入する散歩道のようなものが幾つかあります。
夏場は虫が大量発生するので、うかつに侵入できなかった(...撃退された)のですが、この時期ならば虫も休眠しているはずと思い、早速侵入してみました。

これは、ちょっとした坂道を上っている途中です。
道一面に枯れ葉が敷き詰められています。これはこれで奇麗ですね。
IMG_0793.jpg

そんなこんなで散策していたのですが、ここで衝撃の生物に遭遇しました。
これを見て下さい。
IMG_0800.jpg

トンボです。この日は、11月10日ですよ?
まさか、まだ生き残っているとは驚きました。

こいつの他に、もう一匹姿を見ました。
さすがに、弱ってフラフラしてましたけどね。

帰り道

ゴールの北広島まで到着!
そして、なにもせずに反転!

...いや、だってこの辺りって何もないし。

帰り道、時間帯が悪かったのか、雪虫が大量発生。
まさに、雨のような虫の中を突破するはめになりました。
体中にビッシリ虫が付着、落としても落としても付いてきやがる。

いや、本当にキツかったです。
もう二度と、この時期はサイクリングにでない事を自分に誓いました。


スポンサードリンク

PageTop

NetCOBOLのソース編集をExcelマクロで作ってみた(共通関数)

初めに

※ 本記事は、ExcelマクロでCOBOLソースを自動編集させるマクロを作る記事の第2話です。

共通関数

今回は、commonモジュールを作成します。
COBOLソース編集(プロジェクト)

ソース

バイト数を取得する関数を作ります。
単純にLenB関数を使用するとUnicodeの関係で、半角文字のバイト数が2とかになります。
なので、コード変換してからLenB関数でバイト数を取得しています。

' 機能 : 実際のバイト数を返す。
'
' 返り値 :
'
' 引き数 : ARG1 - バイト数を取得する文字列
'
' 機能説明 : 引数で指定された値のByte数を取得します。
'

Public Function K_LenByte(ByVal myValue As String) As Integer
'Unicodeからシステム規定コードに変換してから、Byte数を取得して返却します。
K_LenByte = LenB(StrConv(myValue, vbFromUnicode))
End Function


次に、文字列から指定した範囲の文字を取得する関数を作成します。
ようするに、mid関数のバイト対応ですね。

' 機能 : バイト数を使用した文字列取得
'
' 返り値 :
'
' 引き数 : ARG1 - 文字列を取得する文字列
' ARG2 - 開始位置(バイト数)
' ARG3 - 取得バイト数
'
' 機能説明 : 文字列から指定したバイト数で文字列を取得する
'

Public Function K_midByte(myValue, myStart As Integer, myLenByte As Integer) As String

'変数宣言
Dim myString As String '戻値
Dim myWorkStr As String '追加文字
Dim myGen As Integer '戻値のByte数
Dim i As Integer 'ループカウンタ

'戻値のByte数
myGen = 1

'1文字ずつ読み込んで、指定したバイト数の間は文字を追加出力する
For i = 1 To Len(myValue)

'追加用文字を取得します。
myWorkStr = Mid(myValue, i, 1)

'戻値のByte数が指定Byteの範囲内である
If myGen >= myStart And myGen <= myStart + myLenByte Then
'戻値に1文字追加する
myString = myString & myWorkStr
End If

'追加文字を含めたバイト数取得
myGen = myGen + K_LenByte(myWorkStr)

'戻値のByte数が出力範囲を超えた場合、ループを抜ける
If myGen >= myStart + myLenByte Then
Exit For
End If
Next

'終了処理
normalEnd:
K_midByte = myString
End Function


第1話(概要): NetCOBOLのソース編集をExcelマクロで作ってみた(概要)
第2話(共通関数): この記事です
第3話(専用関数): NetCOBOLのソース編集をExcelマクロで作ってみた(専用関数)
第4話(Cobolソース編集) : NetCOBOLのソース編集をExcelマクロで作ってみた(Cobolソース編集)
第5話(実行結果) : NetCOBOLのソース編集をExcelマクロで作ってみた(実行結果)

投稿記事の一覧:目次

次回

次回は、commonLocalモジュールを掲載します。
スポンサードリンク

PageTop

NetCOBOLのソース編集をExcelマクロで作ってみた(概要)

ソースの編集に悩む

COBOLのソースコードをテキストエディタで作成しているのですが、やはり不便を感じます。
昔、ホストコンピュータで開発していた時には悩まなかったことを、何とかできないだろうか?

やりたいことは、こんな感じですね。


1.一連番号領域(1Byte~6Byte)に自動的に連番を振りたい
2.後方空白の除去
3.SQL文中に単一行コメントがある場合は、75Byte以降に移動する


1,2は単純なソース編集。
3はプリコンパイルでエラーが発生する現象への対応ですね。

方針

本当は、EclipseのプラグインでCOBOLのソース編集が出来れば一番だったんだけど、探しても見当たらない、又は有料(しかも高い)だったりします。

フリーソフトもいろいろ探したんですけど、使えるのが見つからない。
というか、無駄に機能が多すぎる。

私が、開発端末でやることはソースの編集だけなので、統合開発環境のような凄いのは不要なんですよ。

...いっそのこと、自作するか。
Excelマクロで十分でしょ。

完成想定図

シート上には、処理を起動するボタンだけを設定します。
COBOLソース編集(シート)

標準モジュールを3つ用意します。
COBOLソース編集(プロジェクト)

これで動くように、作っていきますか。

第1話(概要): この記事です。
第2話(共通関数):NetCOBOLのソース編集をExcelマクロで作ってみた(共通関数)
第3話(専用関数): NetCOBOLのソース編集をExcelマクロで作ってみた(専用関数)
第4話(Cobolソース編集) : NetCOBOLのソース編集をExcelマクロで作ってみた(Cobolソース編集)
第5話(実行結果) : NetCOBOLのソース編集をExcelマクロで作ってみた(実行結果)

投稿記事の一覧:目次

次回

次回から、各モジュールを載せていきます。
スポンサードリンク

PageTop

SQLテクニック(ダブルクォートの置換)

CSVだよ

SELECT文の実行結果を、CSVでダウンロードするっていう処理があります。
ちなみに、SQLでは単純にデータ抽出だけを行って、JavaでCSV形式へ変換させています。
CSV編集では、項目の前後に"(ダブルクォート)を追加しています。

ダウンロードしたCSVは、そのままExcelで表示するのですが、抽出結果に"(ダブルクォート)が入ってくる場合、Excel側で項目の区切りが正しく判定できない状態で表示されてしまいます。

うーむ。
そこそこ優秀なソフトだと、項目内に"(ダブルクォート)があっても表示してくれるんですけど、Excelはダメみたいですね。

変換する

まぁ、対応方法はいくらか考えついたのですが、今回はSELECT文の実行時に、"(ダブルクォート)を'(シングルクォート)に置換することにしました。

サンプル1

REPLACE関数を使用します。
シングルクォートを二つ並べることで、一つのシングルクォートとして扱います。

SELECT 担当者コード ,
REPLACE( 担当者コード , '"' , '''' )
FROM 担当者マスタ


サンプル2

上記の方法でも良いんですけど、シングルクォートを4つも並べるのが気持ち悪い。
...いや、個人的に嫌いなだけなんですけどね。
なので、CHR関数を使ってみました。

SELECT 担当者コード ,
REPLACE( 担当者コード , CHR(34) , CHR(39) )
FROM 担当者マスタ


CHR関数は、引数で指定した文字コードから値を返却する関数です。
この場合、CHR(34)がダブルクォート、CHR(39)がシングルクォートですね。

スポンサードリンク

PageTop

拠点のサーバを集約できないのか?(SMB速度検証)

構想

各拠点にサーバを置いているのですが、こいつをIDCに集約できないか検討してみました。
大体の機能はIDCに集約できそうだったのですが、最終的に問題になったのがファイル共有です。

現状

現状、サーバを置いていない拠点もあって、そこの人たちにはIDCのファイルサーバを解放しているのですが、遅すぎてクレームの嵐。
まぁ、回線速度が10Mbps程度のWANを通してるんですから当然ですけどね。

こうなると、拠点でちょっとコンピュータに明るい人は「LANディスクを設置させてくれ」って言ってくるんですよね。

いや、設置は構わないがバックアップを取得できないんで、壊れたら全てを失いますよ。
かといってダメとは言いずらいし...
きっと↓みたいなことになるんだろうなぁ。


A:「大事なデータはIDCのファイルサーバに保管すれば良いだろ。」
私:「使用している人はデータをどこに保存しているかなんて意識してませんって!」
A:「教育すればいいだろ。」
私:「無理だし、無駄ですって。」
A:「とにかく、大丈夫だから。」
私:「...」


んで、やっぱり壊れたとします。


拠点の人:「ファイルが見れない!」
私   :「壊れたLANディスクには大事なデータは無いですよね?」
拠点の人:「LANディスクって何?」
私   :「...今まで共有ってどうやって使ってました?」
拠点の人:「なんか画面にショートカットがあって、その先に保存してるだけ。」
私   :「...(やっぱり)」
拠点の人:「何とかしてよ!」
私   :「...」


ですよねー。


私:「だから言ったじゃないですか。」
A:「しょうがないだろ。教育もしてたんだし俺の責任じゃないよ。」
私:「...いや、責任とかじゃなくて現場が困ってるんですよ?」
A:「知らないよ。」
私:「...」

※ フィクションです。

検討

素直に拠点にサーバか、WSS対応NASでも置いた方が良いと思うんですけど、使い物になるか検証してみました。

現状のサーバOSはWindows2003 R2。新しいサーバOSはWindows2008 R2とします。
んで、クライアントのOSはWindowsXP or Winsows7 です。

たしか、Windows2008 とWinsows7 だとSMB2が使用されるはず。
もしかして、現状のSMBからSMB2に変わる事で速度が向上しないだろうか?

とりあえず、実験してみました。

1.テスト内容

クライアントからサーバ共有に対して、ファイルの書込みと読込を行い実行時間を計測する。

2.環境

通信回線    : 100Mbps
ファイルサイズ : 1.17GB 

※ 通信回線は、このテスト以外でも使用しているとします。

3.実験結果1(書込み速度)

WindowsXP → Windows2003 R2 = 3分51秒
WindowsXP → Windows2008 R2 = 3分46秒

Windows7 → Windows2003 R2 = 2分3秒
Windows7 → Windows2008 R2 = 1分49秒

4.実験結果2(読込速度)

WindowsXP ← Windows2003 R2 = 3分58秒
WindowsXP ← Windows2008 R2 = 2分59秒

Windows7 ← Windows2003 R2 = 1分58秒
Windows7 ← Windows2008 R2 = 1分49秒

テスト結果

WindowsXPからサーバへの速度が、なんか安定しないですね。
そして、相手サーバのOSが2003、2008のどちらであっても速度が変わりません。
実測値: ((1.17GB × 1024) / 230秒) × 8 ≒ 42Mbps

Windows7の場合、相手サーバのOSに左右されずに安定した性能になってますね。
サーバOSが2008の場合、SMB2が使用されて高速に転送されるかと思ったのですが、目に見える程の差になりまんでした。
実測値: ((1.17GB × 1024) / 120秒) × 8 ≒ 80Mbps

むしろ、クライアントのOSによる差が大きかったですね。
XPと7で倍近い速度差になるとは思ってませんでした。

考察

SMBのバージョン差による性能向上は認められなかったのですが、クライアントOSの差による性能向上は目に見張るものがありますね。
あるいは、クライアントをWindows7で統一できれば、IDCのファイルサーバを使用しても現実的に使用できる速度が出るかも知れません。

...まぁ、WindowsXPは後2年以上残るので、どちらにしても今回は見送りですね。

スポンサードリンク

PageTop

powerShellの実行ポリシーを変更してみた(Windwos7)

実行ポリシーが変更できない

私が使用しいるパソコンのOSはWindwsXPです。
その関係で、powerShellを動かしたことがあるのも、WindowsXPとWindows Server2008 R2 の2つだけだったりします。

んで、ちょっとした実験のためにpowerShellで作ったスクリプトを上司の端末(Windows7)で実行したところ、「スクリプトの実行がシステムで無効になっているため...」とエラーメッセージが表示されて実行できない。

...あぁ、実行ポリシーの初期値って「全てNG(Restricted)」だったっけ。
というわけで、以前に自分で書いたブログ(powerShellの実行ポリシーを変更してみた)を見ながら実行ポリシーを変更しようとしたところ、こんなエラーが発生しました。

powerShellポリシー変更_失敗(Win7)

写真だけだと見づらいので、文字でも書いときます。

PS C:¥Users¥sysmngr> Set-ExecutionPolicy RemoteSigned

実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies
のヘルプ トピックで説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y) [N] いいえ(N) [S] 中断(S) [?] ヘルプ (既定値は "Y"): y
Set-ExecutionPolicy : レジストリ キー 'HKEY_LOCAL_MACHINE¥SOFTWARE¥Microsoft¥PowerShell¥1¥ShellIds¥Microsoft.PowerShell
' へのアクセスが拒否されました。
発生場所 行:1 文字:20
+ Set-ExecutionPolicy <<<< RemoteSigned
+ CategoryInfo : NotSpecified: (:) [Set-ExecutionPolicy]、UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.SetExecutionPolicyComma
nd

PS C:¥Users¥sysmngr>


...あれ?

管理者にしないと…

レジストリが云々、アクセスが拒否とか出てるので、大方、管理者権限を要求しているんだろうと思って、Windowsからログオフ、管理者権限(Administrator)を持っているユーザーでログインして再度実行、ところが同じ結果になりました。

......あれー?

忘れてました

Windows7の管理者権限って、アプリケーション単位に与えないといけないのを、すっかり忘れていました。

まず、管理者権限でpowerShellを起動します(powerShellを管理者で実行(Windows7))。

改めて、ポリシーを変更したところ、コマンド実行に成功しました。

powerShellポリシー変更_成功(Win7)

成功の方も、メッセージを書いときます。

PS C:¥windows¥system32> Set-ExecutionPolicy RemoteSigned

実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies
のヘルプ トピックで説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y) [N] いいえ(N) [S] 中断(S) [?] ヘルプ (既定値は "Y"): y
PS C:¥windows¥system32> Get-ExecutionPolicy
RemoteSigned
PS C:¥windows¥system32>


後書き

やりたかったのは、とあるサーバーの共有ファイルに対する書き込み&読込速度の検証でした。
と言っても、難しいことはせずに単純に1ファイルあたりの実行時間だけを出したかっただけなので、別にコピー&ペーストでも十分可能だったんです。

わざわざpowerShellなんて使ったのは、コピー開始と終了のタイムスタンプを表示させたかっただけ。
つまり、ストップウォッチで計るのが面倒だったからなんですが、かえって手間が掛かる事になってしまいました。

上手くいかないものですねぇ。
スポンサードリンク

PageTop

powerShellを管理者で実行(Windows7)

■ 管理者権限

Windows7でpowerShellを実行しようとすると、管理者権限での実行を要求されることがあります。

...というか、書込みエラーだの、レジストリが云々だのと訳のわからんエラーを出しやがる。

管理者権限が無くてエラーになるんなら、最初からそういうメッセージを出してくれよ!

■ Windows7での管理者権限

Windows7(Vistaもそうだったかな?)では、管理者アカウントでログインしてもアプリケーションは通常ユーザーでの起動と同じに扱われます。

アプリケーションを管理者として使用する場合、一時的に管理者として実行される方法と、常に管理者として実行させる方法がありますが、今回は一時的に管理者としてpowerShellを実行することにします。

■ 起動

[スタート]→[すべてのプログラム]→[アクセサリ]→[Windows PowerShell]を開いて、Windows PowerShell を右クリック。

表示されたメニューから「管理者として実行」をクリックしてやればOKです。

powerShell管理者(Win7)


投稿記事の一覧:http://harikofu.web.fc2.com/

--- blog end ---


スポンサードリンク

PageTop

初雪!(日本酒美味しいなぁ)

初雪!

なんか外が暗いと思ってみて見ると、雪が降っていました。
初雪1(2012年)

というか、吹雪いていますね。
初雪2(2012年)

そろそろとは思ってましたが、ついに来てしまいましたね。
今日が休日なのが救いですよ。

この季節はこれ!

まぁ、降った物はしょうがないので、諦めて暖まる事にしました。
準備は整っていますし。
日本酒小瓶シリーズ

購入は、ラルズマート新ほくと店。
近所って訳じゃないんですけど、最近通っていた歯医者の近くなので、帰りによってたんですよ。
なんか、日本各地のお酒の小瓶シリーズみたいだったので、全種類購入してみました。

熱燗もいいですけど、暖房ガンガン焚いて、冷やで飲むのも良いですよね。

スポンサードリンク

PageTop

他メーカの写真用紙で印刷するとどうなる?

プリンタ買い替え

元々はHPのプリンタを使っていたんですが、EPSONに乗り換える事にしました。
印刷品質には問題を感じてなかったのですが、周辺機器の未対応状況が酷すぎて辛かったんです。

例えば、DVDにラベルを張るとします。
適当なフリーソフトとかで印刷しようとすると、EPSONやキャノンはテンプレートとかに出てくるのに、HPは出てこない。出てきたとしても、実際に印刷するとやたらと位置ずれする。とかですね。

まぁ、微調整すれば良いだけなんで、我慢して使っていたんですけど、機械自体が古くなってきたので思い切って買い替える事にしました。

写真用紙が余った

HPのトナーは、写真用紙とトナーがセットになって販売しているのがあって、これを買っていました。
問題なのは、まともに印刷すると用紙が余るってことです。
写真用紙とトナーがセットなんですが、このトナーを全て写真用紙の印刷に使っても、用紙がかなりの枚数余ります。
結果、大量の写真用紙が蓄積されてしまいました。

リサイクルショップに持ち込んでみたんですけど、案の定、買い取り拒否されました。
(まぁ、当然か…)

再利用してみたが…

もったいないので、購入したEPSONプリンタ(EP-803AW)でも使う事にしたんですが、印刷してみると凄く汚い。
一瞬、「EPSONの印刷品質が悪いのか?」とか思ったのですが、それにしても汚すぎる。
もしやと思い、EPSON純正の写真用紙を使ったところ、奇麗に印刷できました。
うーむ。

こうなります

HPの用紙を使用して印刷した写真の一部です。
左下の枯れ葉の部分に注目して下さい。
用紙比較(HP)

今度は、EPSON用紙を使用した印刷結果です。
左下の枯れ葉の部分も、奇麗に印刷されています。
用紙比較(EPSON)

画像で見ると、それほどでもなく感じるかもしれませんが、実際にはかなりの差になります。

HPは悪くない

こうして書くと、HPが悪く聞こえるかもしれませんが、決してそんな事はありません。
HPプリンタ&HP写真用紙では、EPSONと同等以上の印刷品質を誇っていました。

出来れば、HPのプリンタでEPSON写真用紙を使用して印刷もしてみたかったのですが、すでに旧プリンタは廃棄済みなので検証は出来ません。

本当は、いろいろなメーカー間での比較が出来れば面白いんですけど、そんな予算(と暇)はないので、ここまでですね。

…それにしても、これで大量に余ったHP写真用紙は捨てるしかないですね。
勿体ないけど、しょうがないですかね。
スポンサードリンク

PageTop

グッピーを大量死させてしまった

注意


※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

ここから下に、グッピーが大量死している、残酷な画像があります。
そんなの見たくないという方は、お引き取り願います。

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※


エサが無くなった

ある日、買い置きのエサが切れてしまいました。
最初は素直に買いに行こうとしたのですが、ふと思い立って飼育道具をしまっている戸棚を漁ってみました。
残念ながら、グッピーの餌はなかったのですが、メダカのエサを発見しました。

以前は、60cm水槽で飼育していたんですが、メンテナンスが面倒になって小さな水槽に買い替えたんです。
たしか、その時に水槽と一緒についてきたもののはず。

昔、メダカとグッピーを同じ水槽で飼っていたことがあるのですが、その時は同じエサで問題なく飼育できていたので、しばらくはこれを使ってみる事にしました。

念のため、少量を与えて食べてくれる事を確認。
よし、大丈夫そうだ。

…この時は、そう思ったんです。

経過

数日後、朝起きて水槽を覗くと、グッピーが1匹亡くなっていました。
残念な話ですが、寿命以外にも様々な要因(病気とか)でこいつらは亡くなるので、その時は気にしてませんでした。

その日の晩、仕事から帰ってみると、さらに二匹なくなっていました。
違和感は感じたんですが、その日はクタクタだったので「水質でも悪化してたか?」程度に考えていました。

…そして

大惨事

翌日、大惨事になっていました。

謎の大量死(全景)

謎の大量死(詳細)

対応

飼育していたグッピーの半分以上を一気に失うという、かつてない事態に流石に冷静さを失いました。

とにかく、亡くなったグッピーを葬って環境の改善を開始。
濾過機の清掃、水の入れ替え、水槽のコケの除去、などです。

掃除のせいで濁っていた水が落ち着くまで待ってから、エサを与えました。
ところが、食べてくれない。口に含むんですが、すぐに吐き出してしまいます。

…あれ、もしかして。

急遽、グッピー用のエサを用意して与えたところ、今度は食べてくれました。
ってことは、やっぱり餓死していたようです。

言い訳

私、エサをやるときも濾過器は動かしたままにしてるんですが、それがマズかった。
グッピーが食べようが食べまいが、濾過器で水が拡散されるので、エサは水中に消えるんですよね。

おかげで、こんな事態になるまで気付きませんでした。

これでは、生き物を飼う人間として失格です。
大反省ですね。
スポンサードリンク

PageTop

powerShellを2重に起動できなくしたい

■ 要件

powerShellで作ったとある処理を、サーバーのログオン時に実行させています。
テスト段階では問題なく動作していたんですが、実運用を開始したところ、時々異常終了するようになりました。

原因を調べたところ、そのサーバーにリモートデスクトップで接続(ログイン)したせいで、powerShellの処理が2重起動したことが原因でした。

サーバーの遠隔操作ソフトはあるので、リモートデスクトップで接続しない運用にしても良いのですが、この手の運用ルールの追加は、大体ろくな結果にならない。

なんとか2重起動を防げないだろうか?

■ サンプル

ミューテックスという仕組みを利用すれば、2重起動を防げそうです。
10秒待機して終了するだけの単純な処理を作成して、そこにミューテックスを追加します。
Write-Output ('処理を開始します。   ' + (Get-Date -format yyyyMMdd_HHmmss)) 

# ミューテックスを作成します。
# 他ユーザーからの実行もあり得るので、「Global¥」を付けてグローバル・ミューテックスを利用します。

$mutexObject = New-Object System.Threading.Mutex($false, "Global¥MUTEX_TEST")

# シグナルを受信します。戻値がFalseの場合、処理を終了します。
# ※ Falseの場合、別のスレッドでミューテックスが作成されています。

if (-not $mutexObject.WaitOne(0, $false)) {
Write-Warning "既に処理が実行されています。"
Read-Host '何かキーを押すと、処理を終了します。'
exit
}

# 10秒待機します。
Start-Sleep -Seconds 10

# ミューテックスを解放します。
$mutexObject.ReleaseMutex()

# ミューテックスのリソースを解放します。
$mutexObject.Close()

# 終了メッセージ
Write-Output ('処理を終了します。   ' + (Get-Date -format yyyyMMdd_HHmmss))
exit

# -------------------------
# 前回の異常終了検出処理
# -------------------------

trap [System.Threading.AbandonedMutexException] {
Write-Warning "前回の処理で強制終了が発生しています。処理は続行されます。"
continue
}


解説

ミューテックスの使用方法の概要は、ミューテックスオブジェクトの作成、シグナル確認、ミューテックスオブジェクトの解放・廃棄になります。

1.ミューテックスオブジェクトの作成

New-Objectコマンドレットで、インスタンスを作成します。
作成するのは、System.Threading.Mutexクラス(.NET Frameworkのオブジェクト)。
コンストラクタの第一引数は、False固定、第二引数に適当な名前を付けときます。

この時に、先頭を「Global¥」とプレフィックスを付けることでシステム全体を対象とした2重起動の抑止が可能になります。要件が「リモートデスクトップでログインされた時の2重起動抑止」なので、これが無いときちんと動きませんでした。

2.シグナルを受信

WaitOneメソッドの戻値から、2重起動を検出します。
このメソッドの本来の役割は、「他のスレッドが使用している資産が解放されるまで待機する」で、戻値にTrueが返却された場合は、資産を使用できる状態になったということです。

第一引数は待機時間です、今回は待機する必要はないので0でOK。
第二引数は、マニュアル読んだんですけど、意味が分かりませんでした。
今回の用途では、Falseを設定しておけば良いようです。

このメソッドの戻値がFalseになる、ということは、既に処理が実行されているということですので、2重起動の警告メッセージを表示して処理を終了させます。

3.後始末

作成したミューテックスを解放します。
ReleaseMutexで解放、Closeで廃棄です。

このあたりは、オブジェクトを使用した時のお約束ですよね。

4.前回の異常の検出

powerShellが項番3の後始末をしない状態で終了された場合、次回の起動時にWaitOneメソッドで例外(AbandonedMutexException)が発生します。
十分にあり得る話なので、エラートラップを仕込んで、処理を続行できるようにしています。

■ 実験開始

まず、単独で実行してみます。
通常時は問題なく動作するようです。
Mutexi(正常)

では、前回異常時のエラートラップを実験してみます。
待機処理の実行中にCtrl + C で処理を終了させ、再度処理を実行します。
Mutexi(前回‘異常)

一見、上手く動作したように思えたのですが、思ったようには動いてくれませんでした。

例えば、powerShellの実行画面を2つ起動して、片方で処理を実行して途中で終了させます。
この状態で、もう一つの画面で同じ処理を実行したところ、前回異常時のエラーメッセージは表示されませんでした。

...なんでだろ?まぁ、前回異常時も処理を続行させるのが目的なので、ここでは目をつぶります。

最後に、本命の2重起動のチェックをしてみます。
画面を2つ同時に起動して、片方の画面で実行中に、もう片方でも実行します。
Mutexi(2‚重起動エラー)

うむ、2つ目の処理が動きませんね。これで行けそうです。

投稿記事の一覧:http://harikofu.web.fc2.com/

--- blog end ---
スポンサードリンク

PageTop

powerShellで無限ループと待機処理

■ 状況

あるフォルダにファイルが保存された時に、そのファイルに対して何らかの処理を実行する。

ファイルが保存されるのは、7:00 〜 0:00 の間に不定期に保存される。処理を実行するサーバーは、6:30に再起動するが、それ以外の時間帯は常に稼働している。

という条件で動作する処理を作る必要が生じました。さて、どうしようか?

■ サンプル

特別な環境を用意する程のこともないので、powerShellで実現してみようと思います。
必要な処理は、無限ループと待機処理ですかね。
# 無限ループです。
# 強制終了されるまで、永遠に処理を繰り返します。

while(1) {

# メッセージを表示します。
Write-Output ('日時:' + (Get-Date -format yyyyMMdd_HHmmss))

# 30秒待機します。
Start-Sleep -Seconds 30
}


※ メインの処理は後で作るとして、ここでは代わりにWrite-Outputを実行させておきます。

■ 解説

1.無限ループ

無限ループは、while文で実現します。
while文は、条件が真(True)である間は処理を繰り返します。

そして、powerShellでは0は偽(False)を表し、0以外は真(True)を表します。
なので、サンプルのように条件に1を指定すると、真(True)ということになり、無限ループが実現できます。
これは、C言語あたりと同じ仕様ですかね。

ちなみに、「 while($True) 」というように、boolean値を直接指定しても動きます。

2.待機処理

連続実行させるのも良くないので、30秒のインターバルを置いて処理を実行します。
powerShellの待機処理は、Start-Sleepコマンドレットで実現できます。

オプション -Seconds で待機する秒数を指定できます。

■ 実行

実行結果は、下記のようになりました。
ログの時間を見る限り、30秒の待機処理が機能していることが分りますね。

waitShellの実行画面

投稿記事の一覧:http://harikofu.web.fc2.com/

--- blog end ---

スポンサードリンク

PageTop

powerShellがマイ ドキュメントから実行できない

■ いきなり躓いた

久しぶりにpowerShellを使おうとしたら、なぜか実行できない(--;)

シェルは「C:\My Documents」にあります。
内容は、こんな感じです。
# 確認メッセージを表示します。
Write-Output ('日時:' + (Get-Date -format yyyyMMdd_HHmmss))


powerShellを起動して、作成したシェルをドラッグ&ドロップ、そしてEnterキーを押下すると、処理が実行されません。
powerShell(Harf My Docu)

あれ?なんでだ?

■ なんで?

とりあえず、いろいろ試して見ます。

1.シェルをDドライブ直下に移動して実行

これは、きちんと動きました。
powerShell(Harf D)

2.半角スペースを含めてみる

Dドライブの「AAA BBB」というフォルダから実行します。
これはダメでした。
powerShell(Harf D FolderSpace)

今度は、Dドライブ直下から、シェルの名前自体に半角スペースを追加して実行します。
これもダメでした。
powerShell(Harf D NameSpace)

3.全角スペース

同じ条件下で、半角スペースを全角スペースにして実行します。
フォルダ名、ファイル名のどちらでも動作できました。

powerShell(Harf D FolderLSpace)

powerShell(Harf D NameLSpace)

■ 犯人は判った、こうしよう

多くの言語と同じく、powerShellでは半角スペースを意味の区切りと認識するようです。
なので、powerShellに半角スペースをコマンドの一部だと教えてやれば動きそうです。

1.エスケープシーケンスを使う

powerShellでのエスケープシーケンスの使用は`(バックスラッシュ)です。
なので、半角スペースの前に`を追加してやれば、動作させられました。

powerShell(Harf バックスラッシュ)

…しかし、この方法だと手間が掛かりすぎる。
毎回、コマンドを手打ちするってのも手間だしね。

2.&を使う

であれば、先頭に「& 」を付けて実行するまでの話です。
これなら、「& 」を打った後にシェルをドラッグ&ドロップしてやるだけです。

powerShell(Harf &)


投稿記事の一覧:http://harikofu.web.fc2.com/

--- blog end ---

スポンサードリンク

PageTop

静かな環境で働かせてくれ!

始めに

ここで書くのは、職場環境の雑音に関する愚痴のようなものです。
泣き言なんか聞きたく(読みたく)ないって方は、見ないで下さい(ペコリ)





静かな環境で仕事させて欲しい

騒音の聞こえない環境で仕事がしたいって時がありませんか?

私の近くに座ってる人が、騒音メーカーで、とにかく不快な音をたてるんです。
キーボードは力強く「ダダダダダダ」と連打。
電話で話していると、そいつの打鍵音のせいで、相手の声が聞こえない程。

お茶を飲ませれば「ズズズズズー」とすする。
何を勘違いしているのか、お茶はすすって飲むのがマナーと信じているらしく、常にわざと音を立てて飲む。
(人を不快にさせるマナーって存在するのかよ?)

声には張りがなく、だらけた感じ。
分からない事があると、短距離走の選手のごとく席を立ち「教えてー」「教えてー」とあちこち巡回を始める始末。
見殺しにする訳にも行かない(放置すると、そいつ意外以外の別の人が困るから)ので教えると、返事は「はぁ」。
…「はぁ」ってなんだよ!

さらに、教えた事は一週間も持たずに脳みそから消去される機能も搭載されています。
(もちろん、メモをとるなんて事はしない)

こんな有様なんで、最近は声を聞くだけでイライラするようになりました。
静かな環境っていうか、やつの立てる音を遮断したいんですよ。

結局、我慢するしかないのか

思いついたのが、イヤフォンで耳をふさいで音楽聞くって手です。
ただ、やっぱりこれは出来ません。

電話が鳴っても聞こえない、周りの人の声も聞こえない、さらに逆の立場で考えると、そういう人には話しかけ辛い。
完全な個人作業者や、パーティションで区切られてるような職場環境だったら問題なさそうですけど、チームの一員として仕事をするのであれば、良くないですよね。
なにより、年配の方が賛同してくれなそうですしね。

まぁ、正攻法は異音を立てる人を説得して、静かにしてもらうことなんですけど、言って分かる人じゃない(というか、すでに説得は失敗している)。

我慢するしかないのかなぁ。

耐えられなかった…

という訳で、諦めて異音に耐える事にしました。
うるさいって言っても、どこぞの騒音おばさんのごとく、常時異音を立てる訳でもないですからね。

ところが、数ヶ月前に私に大きな仕事が舞い込みました。
内容は、既存システムへの機能追加で、新規の画面や帳票などは発生しないのですが、影響範囲が広く、数十の機能に対して修正しないといけない事態になりました。しかも期限は一ヶ月半。

この状況で、役割分担はこんな感じ。
要件定義:私(他2名)、仕様設計:私、プログラミング:私、テスト:私、教育&運用支援:他。

私の会社、元々はホストコンピュータ&COBOLというレガシーシステムで、数年前にWebシステムに切り替えたという経緯があって、現状ではこの新システムに対して設計やプロブラミングが出来るのが私しかいません。
なので、設計とプログラミングが私なのは良いんですけど、テストは手伝って欲しいとお願いしたら、嫌そうな顔してそっぽ向かれました。
彼の理論によると、「プログラムを組んだ人間が一番分かってるだろ」だそうです。
…おのれ、呼吸するレガシーめ。

期限まで時間がないので、残業祭りが勃発(参加者は私一人)。
いい加減、心身ともにキツくなってきて、そうなると、奴がたてる異音がキツくなってくる。

問題なのは、集中できない事じゃなくて、集中している時に、奴が立てる音が原因で、集中を切られることなんです。
ちなみに私は、集中して周りが見えなくなる状態を「世界に入る」、集中が切れたて周りが見えるようになった状態を「現実に戻る(される)」と心の中で言っています。

そんな状況の中、奴の異音で集中を切られる事が多発して、いい加減私もイラッとして、思わず「うるせぇ!俺を現実に引き戻すな!」と叫びそうになりました。

…マズい、頭がおかしくなったと思われる。

静かな世界を求めて

上司に言ってもどうしようもないと判断して、自衛のための行動を起こす事にしました。
目をつけたのは、サーバー室です。こいつは元々は、ホストコンピュータを置いていた部屋で、今ではほとんど使用していません。
しかし、その性質上、ネットワークは生きていて、しかも空調設備も整っています。
何より、人が誰もいないので静かです。

え、サーバーの稼働音?
ふん、奴の立てる音に比べれば、小川のせせらぎのようなモノですよ。

という訳で、資料一式とパソコンをサーバー室に無許可で移動。
作業開始したところ、順調順調!

上司に怒られるかとも思ったのですが、なにも言われませんでした。

結局どうなった

集中できる環境のおかげで、なんとか、期限に間に合いました。
まぁ、稼働後にバグが10件以上出たりしましたけど、修正規模から考えれば想定の範囲内。

…俺一人で、テストしきれる訳ないだろ。

状況終了後、素直にサーバー室から自分の席に戻りました。
ここで働けば能率が上がるのは確かなんですけど、周りの目が気になりますしね。

最新の記事:http://harikofu.blog.fc2.com/
投稿記事の一覧:http://harikofu.web.fc2.com/

--- blog end — スポンサードリンク

PageTop

Excelで中止機能付きのマクロを作ってみた(フォーム編)

前回の問題

前回(Excelで中止機能付きのマクロを作ってみた)で、実行中のマクロを停止する機能を紹介したのですが、実は問題があります。

処理実行中に、適当なセルをクリックして文字を打ち込むと、マクロが終了してしまいます。
中止しなくても止まる

どうやら、DoEvents関数の実行時に何らかのイベントが発生した場合には、処理が終わってしまうようです。
上記の例では、シート内のセルを変更した時に発生する「Worksheet_SelectionChange」が動いたことが原因と思われます。

さて、これを何とか出来ないものだろうか?

試行錯誤

ダメもとで、いろいろ試して見ました。
例えば、Application.EnableEventsプロパティやApplication.ScreenUpdatingプロパティを駆使して制御できないか?とかですね。もちろん、ダメでしたけど。

他には、どっかに処理中の変数の情報とかを退避しておいて、処理が中断されたら中断された時点から再開できるようにするって手も考えたんですけど、それだと気軽に使えないからダメ。

...まっとうな方法で実現できそうになかったので、疑似的に実現する方法を考えてみます。
ようするに、マクロを実行している間はExcelに触れないって状況を作ってやればいいんですよ。

考えたのは、マクロ実行直後にユーザーフォームを表示して、Excelウィンドウをフォームの下に隠す。
マクロ終了後に、フォームを閉じて、Excelウィンドウをマクロ開始時のサイズに戻すっていう方法です。

サンプル

フォーム名は「macroStopForm」として、件数表示用のテキストボックスと中止用のボタンを配置します。
中止用フォーム

中止ボタン押下時の処理は、前回までと同様にPublic変数「gStopFlag」への設定とします。

' 中止ボタン押下時の処理
'
Private Sub macroStopButton_Click()

'処理中断フラグ = True:中止
gStopFlag = True

End Sub


シート上には、開始ボタンのみ設置します。
前回のカウンタと中止ボタンは、上記のフォームに機能を移動しています。
開始ボタン

開始ボタン押下時の処理は、下記のようになります。

' 処理メソッド
'
Public Sub macroStart()

'-----------
' 変数宣言
'-----------

'ループカウンタ
Dim i As Long

'Excelのウィンドウ状態
Dim myAppTop As Double
Dim myAppLeft As Double
Dim myAppWidth As Double
Dim myAppHeight As Double

'-----------
' 初期処理
'-----------

'Excelウィンドウを標準にします。
Application.WindowState = xlNormal

'処理中断フラグ = False:続行
gStopFlag = False

'現在のExcelウィンドウの状態を退避します。
myAppTop = Application.Top
myAppLeft = Application.Left
myAppWidth = Application.Width
myAppHeight = Application.Height

'フォームを読込ます。
Load macroStopForm

'フォームの位置を画面中央にします。
macroStopForm.StartUpPosition = 2

'フォームを表示します。
macroStopForm.Show (vbModeless)

'Excelウィンドウをフォームの下に隠します。
Application.Width = CInt(macroStopForm.Width)
Application.Height = CInt(macroStopForm.Height)
Application.Top = CInt(macroStopForm.Top)
Application.Left = CInt(macroStopForm.Left)

'-----------
' 処理
'-----------

'ループ
For i = 0 To 19

'1秒待機します。
Call K_StopTime(1)

'5回に一度、中止判定をします。
If i Mod 5 = 0 Then

'フォームの実行件数を更新
macroStopForm.countBox.Value = i + 1 & " / 20"

'OSに制御を返します。
DoEvents

'Excelウィンドウをフォームの下に隠します。
Application.Width = CInt(macroStopForm.Width)
Application.Height = CInt(macroStopForm.Height)
Application.Top = CInt(macroStopForm.Top)
Application.Left = CInt(macroStopForm.Left)

'中止判定
If gStopFlag Then
GoTo stopEnd
End If
End If
Next

'-----------
' 後処理
'-----------

'正常終了
normalEnd:
GoSub commonEnd
MsgBox "終了しました。" & Chr(10) & Chr(10) & "i = " & i
Exit Sub

'中止処理
stopEnd:
GoSub commonEnd
MsgBox "中止します。" & Chr(10) & Chr(10) & "i = " & i
Exit Sub

'終了時の共通処理
commonEnd:

'フォームを終了します。
Unload macroStopForm

'Excelウィンドウを開始時点の状態に戻します。
Application.Width = myAppWidth
Application.Height = myAppHeight
Application.Top = myAppTop
Application.Left = myAppLeft

Return

End Sub


解説

基本的なロジックは前回と同様ですので、まずは前回の記事をご覧下さい(下にリンクがあります)。
前回との変更点を解説します。

1.変数宣言

Excelの位置、サイズを保持する変数を準備します。
画面上の位置、縦横のサイズの4つが必要です。

2.初期処理

ここが、大きく変わった(追加した)箇所になります。

まず、Excelの表示状態を表す「Application.WindowState」プロパティに「xlNormal」を設定して標準ウィンドウにします(ちなみに、xlMaximaizedで最大化、xlMinimizedで最小化)。

次に、ApplicationオブジェクトのTop、Left、Width、Heightの値を、先ほど作成した変数に設定します。
処理終了時には、ここで保持した値からExcelウィンドウの状態を復帰します。

フォーム「macroStopForm」をloadステートメントで読み込みます。
まぁ、いきなりShowメソッドでフォームを表示しても良いんですけど、「まずフォームをロードして、加工してから表示する」っていう事を良くやるんで、フォーム使用時の私の癖になっちゃいました。

そして、フォームを画面中央に表示するために、「macroStopForm.StartUpPosition」プロパティに 2 を設定します。
なお、0は設定しない、1はExcel画面の中央、3で画面左上になります。

これで下準備が終わったので、Showメソッドでフォームを画面表示します。
この時に、Showメソッドの引数に「vbModeless」を設定してモードレスでフォームを表示します。
これを設定しないと、フォームが終了するまで次の処理が実行されません。
...このメソッドに、「処理は続行させるけどシートの操作は許さないって」オプションがあれば、こんな小細工はいらないんですけどね。

最後にフォームの画面上の位置、縦横のサイズをApplicationオブジェクトの対応するプロパティに設定してやります。これで、Excelが表示したフォームの影に隠れる事になります。
サンプルではCIntで整数型にしていますが、そのまま設定しても問題ありません。

3.処理

ここは、前回とほぼ同じです。
ループ内でカウントが5で割り切れる値になるたびに、DoEventsを実行して処理中止の判断を行います。

違いは、カウントの表示先がシートからフォームに変わった事と、DoEvents実行後にExcelウィンドウの位置とサイズの調整(フォームの下に隠す)をしている事くらいです。
位置調整をするのは、ユーザーにフォームの位置を移動された時に、Excelもそれにあわせて移動させるためです。

あと、処理が中止された場合、前回はそこで終了(Exit Sub)していましたが、今回は後処理があるので終了処理に遷移させています。

4.後処理

フォームを終了して、Excelの位置、サイズを処理開始時の状態に復元します。
これは正常時も、途中で中止した時も実行させます。

動かしてみよう

シート上の「開始」ボタンを押すと、Excelが画面から消えて、フォームのみが表示されているように見えるはずです。
処理中にフォームの「中止」ボタンを押下すると、カウンタが5の倍数になるタイミングで処理が中止されます。

ちなみに、今回、処理実行中の画面は付けませんでした。
性質上、実行画面を出すってことはデスクトップを表示しないといけないんですけど、これが汚すぎて人に見せられる状態じゃなかったからです。

油断すると、デスクトップってゴミ置き場になっちゃいません?
そろそろ整理しないとなぁ。

今さら言うことではないが...

ここまで作っといて言うのもなんですが、なんかヤクザな感じがするんですよね。
自分だけで使うツール用としては良いんですけど、他人に使ってもらうExcelには怖くて実装できません。

Excel自体の設定を弄ってるんで、環境によってどんな障害が発生するか分りません。
ありそうなのが「マクロ終了時にExcelウィンドウの位置情報が壊れて、画面外に消えてしまう」ですかね。

なんだかんだ言って、シートなりフォームなりに「処理実行中です。終了するまで操作しないで下さい。」ってメッセージ出すだけにした方が安心して配布できそうですね。

前回:Excelで中止機能付きのマクロを作ってみた
投稿記事の一覧:目次

--- blog end ---

スポンサードリンク

PageTop

Oracleのパーティションで遅延障害が頻発

パーティション化による遅延障害

少し前に、サーバ機のリプレースをしたのですが、それに合わせて既存のテーブルをパーティション化しました。
ところが、こいつが思ったように動かない(--;)
性能向上どころか、遅延障害を量産する結果になってしまいました。

※ 今回の記事は、ただの愚痴で中身はありません。

パーティション化するテーブル

分割したテーブルは、月ごとにデータを蓄積していきます。
そして、このテーブルを使用する処理のほとんどは、年度の単位でデータを抽出する性質があります。

例えば、2012年4月~2013年3月とか、2011年4月~2011年8月とかって感じです。
つまり、抽出開始は常に4月になり、抽出終了は最大で翌年度の3月になります。

なので、年度(4月~翌3月)でパーティション化してやれば「対象年度にのみアクセスされるようになって性能が向上する」という見込みだったのです。

統計情報は再取得しない

ちなみに、統計情報の再取得はしていません。
ものの本とかでは、定期的に統計情報を取得することを進めているのですが、実際には統計情報を再取得することで、安定していた処理で遅延が発生する障害が頻発したので、基本的には再取得はしないようにしています。

Oracleのバージョンアップ(9→11) → 遅延障害が頻発 → SQLチューニング → 遅延解消 → 統計情報の取得 → 遅延障害が頻発 → SQLチューニング → 遅延解消 → 統計情報の取得 → 遅延障害が頻発 ....

これでは、やってられません。
ちなみに、SQLチューニングはヒント句の追加による実行計画の固定です。

運用開始、そして遅延頻発

運用を開始して、暫くは順調に動いていたのですが、新年度になって新しい年度のパーティションを追加したところ、遅延障害が頻発するようになりました。

実行計画を確認したところ、新しい年度(パーティション表)に対してアクセスするSQLの実行計画が、ことごとく変になっている(フルテーブルスキャン、想定外のインデックスの使用など)。
ちなみに、抽出条件を過去の年度にしてみると、あからさまに実行計画が変わります。

統計情報の考察

遅延障害が発生するまで意識してなかったのですが、もしかしてOracleの統計情報はパーティション表のそれぞれに対して情報を取得しているのではないだろうか?

とすると、追加した新年度のパーティション表の情報が統計情報に存在しない(統計情報の再取得はしていないので)。
その結果、コストが正しく算出できなくなり、妙な実行計画の作成に繋がったということなのか?

結局どうした?

最初は、統計情報を再取得しようとも思ったのですが、結局は遅延が発生した処理(SQL)を虱潰しにしてヒント句を追加していくことにしました。

というのも、新年度のパーティション表のデータ件数が少ない状態で統計情報を取り直した時に、Oracleが私の思っている実行計画を作成してくれるか分らなかったからです。
それに、来年度もパーティション表を追加するわけですから、同じ障害を起こしたくなかったんです。

よく「大規模テーブルではパーティションを使うと性能向上する」という話を見たり聞いたりしますが、現実には難しいですね。
もちろん、上手く使えれば有効な機能なんでしょうけど、中途半端な知識を元に「よし、パーティションだ!」とかやると、大参事になるというわけです。

...手間暇かけてパーティション化したのに、メリットをデメリットが上回るのでは意味が無いですよね。
やれやれです。
スポンサードリンク

PageTop

Excelで中止機能付きのマクロを作ってみた

中止機能付きのマクロ

実行中のマクロを中止させる方法を考えてみました。
Escキーを押す以外の方法ですよ。

DoEvents関数

通常は、マクロの実行中は画面が固まって何も出来なくなります。
処理を中止させるためには、処理実行中に外部から操作を受け付けさせる必要があるわけで、どうやら、DoEvents関数を使うことで実現できるようです。

Excelヘルプによると、DoEvents関数は「発生したイベントがオペレーティング システムによって処理されるように、プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数です。」と書いています。
いつものことですが、何言ってるのかさっぱりですね。

まぁ、マクロ実行中に行った操作を反映させることが出来るってことなんでしょうけど、私は「実行中のマクロに隙を作る関数」と理解しました。

事前準備

まず、処理の中断を判断するためのフラグ「gStopFlag」を作成します。
あちことのメソッドから使用するので、Public変数にします。

もう一つ処理を一定時間待機する「K_StopTime」関数を作成しておきます。
この関数は、引数で指定した時間だけ処理を待機します。


Option Explicit

'共通変数「処理中断フラグ」 True:中止、False:続行
Public gStopFlag As Boolean


' 機能 : 指定した秒数処理を停止する。
'
' 引き数 : pStopSecond - 停止する秒数
'
' 機能説明 : マクロの実行を指定した時間停止する。
'
Private Sub K_StopTime(Optional ByVal pStopSecond As Integer)

'停止時刻
Dim myWaitTime As Variant

'引数が省略された場合(または0秒が指定された場合)は、1秒に置き換える
If pStopSecond = 0 Then pStopSecond = 1

'停止時刻を作成します(現在の時刻 + 引数.停止秒数)
myWaitTime = TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + pStopSecond)

'指定時刻までマクロの実行を停止します。
Application.Wait myWaitTime

End Sub


サンプルメソッド

「macroStart」メソッドと「macroStop」メソッドを作成します。

' 処理メソッド
'
Public Sub macroStart()

'変数
Dim i As Long 'ループカウンタ

'処理中断フラグ = False:続行
gStopFlag = False

'ループ
For i = 0 To 19

'1秒待機します。
Call K_StopTime(1)

'シートに実行件数を表示
Sheet1.Cells(2, 3).Value = i + 1

'5回に一度、中止判定をします。
If i Mod 5 = 0 Then

'OSに制御を返します。
DoEvents

'中止判定
If gStopFlag Then
MsgBox "中止します。" & Chr(10) & Chr(10) & "i = " & i
Exit Sub
End If
End If
Next

'処理終了メッセージ
MsgBox "終了しました。" & Chr(10) & Chr(10) & "i = " & i

End Sub

' 中止メソッド
'
Public Sub macroStop()

'処理中断フラグ = True:中止
gStopFlag = True

End Sub


■ macroStartメソッド

処理自体は簡単な内容です。
For...Next ステートメントで20回処理を繰り返します。

K_StopTime関数で1秒待機。
変数 i が5の倍数になるたびに、DoEvents関数を実行して、変数「gStopFlag」にTrue(中止)が設定されていた場合は処理を中止します。

■ macroStopメソッド

変数「gStopFlag」にTrue(中止)を設定します。

実験開始

適当なシートに、作成した2つのメソッドを動作するボタンを用意します。
開始ボタンには「macroStart」メソッドを、中止ボタンには「macroStop」メソッドを実行するようにします。
イベント

テスト1「中止しない」

まず、中止をしないパターンを試して見ます。
開始ボタンを押して、処理が終了するまで待ちます。

実行結果は、こんな感じです。
きちんと最後まで動作しました。
正常終了

テスト2「中止する」

さて、ここからば本題です。
セルC2には、処理中の変数 i の値を書き出しています。

この値が、7になった時点で「中止」ボタンを押下します。
結果は、以下の通りになりました。
中止

7の時点で「中止」ボタンを押下したのですが、画面上はなにもおこらずに、8,9,10とカウントアップ。
11になった時点で、メッセージボックスが表示されて処理が中止されました。

考察

マクロ実行中、画面がフリーズしているように見えますが、マウスやキーボードの操作は受け付けてくれるようです。DoEvents関数でOSに制御を渡すというのは、この時の操作を反映してくれるってことのようですね。

「中止」ボタンを押下した時に実行される「macroStop」メソッドですが、これは、「中止」ボタンの押下時ではなく、DoEvents関数が実行された時点になります。

macroStart開始 → 「中止」ボタン押下 → DoEvents関数 → macroStart中断 → macroStop実行 → macroStart再開 → 処理中止

こんな感じですかね?

ちなみに、DoEvents関数の発行タイミングを5回に一度にしたのは、この手の関数を連発するのは気持ち悪いからです。
OSの内部動作には疎いのでハッキリ言えないところですが、DoEvents関数が行う「OSに制御を渡す」っていう動作が性能劣化や奇妙な障害の原因になる気がしてならないんですよ。

この感覚、わかってもらえますかね?

次回:Excelで中止機能付きのマクロを作ってみた(フォーム編)
投稿記事の一覧:目次

--- blog end ---

スポンサードリンク

PageTop

NetCOBOLからのSQLチューニング

実行計画が変な気がする

とあるSQLがsqlDeveloperとかで手動実行すると数秒程度で終わるのに、NetCOBOLから実行すると1時間以上かかる、という事象がありました。

どうやら、NetCOBOLからだと実行計画が奇妙な作られ方をするようです。
別段、複雑なSQLなわけじゃないんですけどねねぇ。

※ ちなみにDBはOracleです。

とりあえず、NetCOBOLのSQLにヒント句を追加して実行計画を固定することにしたんですけど、これが意外と手こずりました。

チューニング(間違い)

とりあえず、ヒント句を追加してみました。

サンプルはこんな感じ。
TESTDBテーブルをインデックス「INDEX_TEST01」を使用して検索するようにヒント句を追加します。

SELECT

/*+
INDEX(TESTDB, INDEX_TEST01)
*/

FROM
TESTDB,
ARUFU
WHERE TESTDB.AB = '1'
AND TESTDB.TE = '0'
AND ARUFU.TTT = TESTDB.TTT


事前に、sqlDeveloperでヒント句が機能していることを確認してから、ソースをコンパイル&リリース。
そして再実行したんですけど、一向に終わる気配がない。
...あれ?

チューニング(正解)

なんかスペルミスでもしたかと、冷や汗をかきながらヒント句の書式を確認したところ、ヒント句の記述にテーブルとインデックスの間にあったカンマが余計なことが分りました。

× : INDEX(TESTDB, INDEX_TEST01)
○ : INDEX(TESTDB INDEX_TEST01)

修正後のソースはこれ。

SELECT

/*+
INDEX(TESTDB INDEX_TEST01)
*/

FROM
TESTDB,
ARUFU
WHERE TESTDB.AB = '1'
AND TESTDB.TE = '0'
AND ARUFU.TTT = TESTDB.TTT


もう一度コンパイルして再実行したところ、きちんと動きました。

考察

どうやら、NetCOBOLでヒント句を指定する場合、書式を正しく守らないといけないようです。
困ったことに、他のシステム(sqlDeveloperとか)では間違えた方のヒント句でも機能するんで、この件があるまでずっと勘違いしていました。
いやいや、お恥ずかしい。

それにしても、NetCOBOLから実行したSQLの実行計画の作られ方は気になるところですね。
プリコンパイラで奇妙な編集でもしてるのかと思いもしたんですけど、最終的にはOracle側で実行計画を作るわけだし、変な動きをさせる方が難しい気がするんですけどね。

ヒントになりそうなのが、他のシステムでは機能したヒント句が、NetCOBOLでは機能しないということでしょうか?
今までは、プリコンパイラはSQLの書式チェック位しかしていないと思っていたのですが、もしかすると実行計画に影響を与えるような妙な編集とかしてるのかもしれないですね。

まぁ、NetCOBOL(というよりPro*COBOLか?)の内部動作なので、これ以上の調査は難しいんですけど...

とりあえず、変に動かれても困るので、NetCOBOLからSQLを実行する時は必ずヒント句を付けるようにしました。
「何のためのコストベースオプティマイザだ?」と思わない訳じゃないですけどね。
スポンサードリンク

PageTop