2013年5月30日木曜日

centos に oracle11g を導入

オラクルの自前環境をもっていると何かと便利なので centos のエミュレーション環境上に oracle 11g を作成してみた。いろいろハマりどころがあったが、WEB 環境からの接続はうまく行ったり行かなかったりで原因を特定できなかった。しかし、コマンドレベルで scottスキーマを使えるようになったので当初の目的は達成したので良しとしてしまおう。

まずはアカウントの用意

# groupadd -g 1001 oinstall
# groupadd -g 1002 dba
# groupadd -g 1003 asmdba
# useradd -u 1001 -g oinstall -G asmdba,dba oracle
# passwd oracle
ユーザー oracle のパスワードを変更。
新しいパスワード:
新しいパスワードを再入力してください:
passwd: 全ての認証トークンが正しく更新できました。


/etc/hosts の localhost にインストール時に指定したホスト名を加える。

127.0.0.1   localhost localhost.localdomain centos 


一旦ログアウトして、作成した oracle アカウントでログインし直し、oracle 11g をダウンロードする。



ダウンロードしたファイルを展開する。

% cd
% unzip ダウンロード/linux_11gR2_database_1of2.zip
% unzip ダウンロード/linux_11gR2_database_2of2.zip


インストーラーを起動する。

% cd database
% ./runInstaller -jreLoc /usr/lib/jvm/jre-1.7.0-openjdk




メールとパスワードは無視する。



データベースの作成と構成を選択する。



デスクトップクラスを選択する。



キャラクタセットと管理パスワードを設定してインストールする。



インベントディレクトリはそのまま進む。



不足のパラメータやライブラリが表示される。



不足のOSパラメータを設定する。
# vi /etc/sysctl.conf
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
fs.file-max = 6815744
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576
fs.aio-max-nr = 1048576
# sysctl -p
# vi /etc/security/limits.conf
@oinstall     soft      nproc      2047
@oinstall     hard      nproc     16384
@oinstall     soft      nofile     1024
@oinstall     hard      nofile    65536
# vi /etc/pam.d/login
session required pam_limits.so


不足のモジュールをインストールする。

# yum install -y gcc
# yum install -y gcc-c++
# yum install -y compat-libstdc++-33
# yum install -y elfutils-libelf-devel
# yum install -y libaio-devel
# yum install -y sysstat
# yum install -y unixODBC unixODBC-devel


再調査をおこない、poksh でけであれば、全てを無視をおして次にいく。



構成を確認して次に進む。



インストール経過表示



DB作成完了表示



ルート権限でシェル実行



オラクルの起動とscottスキーマの作成

$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.1.0 Production on Fri May 31 18:48:35 2013

Copyright (c) 1982, 2009, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area  744910848 bytes
Fixed Size      1339120 bytes
Variable Size    452985104 bytes
Database Buffers   285212672 bytes
Redo Buffers      5373952 bytes
Database mounted.
Database opened.
SQL>@$ORACLE_HOME/rdbms/admin/utlsampl.sql 
$ sqlplus scott/tiger
SQL*Plus: Release 11.2.0.1.0 Production on Fri May 31 18:53:21 2013

Copyright (c) 1982, 2009, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> quit 


オラクルの終了

$ sqlplus / as sysdba
SQL> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> quit 

2013年5月29日水曜日

virturalboxでcentosを大画面で使いたい。

oracle を動かすために、virtualbox に centos をいれて見ました。いい感じでインストールを完了し、さてフル画面で使うためには、 Guest Addition を追加するのだと思いだして追加してみるとまた罠が待ち受けていた。
よくよく見ると何かをインストールしろと言っている。
# yum install kernel-devel-2.6.32-358.el6.i686
これで一安心と気を撮り直して再度インストールすると、gcc utils がないというのでとりあえず以下を導入してみた。


再度、気を撮り直してインストールすると無事インストール完了。


しかし、罠に引っかかる率高いなぁ。Linux 使いの方には、罠でもなんでもないのでしょうね。

2013年5月23日木曜日

clisp でファイルダンプ

ファイルダンププログラムを clisp でも作成してみた。emacs の初期設定すらもままならない僕にはやはりかなりハードルが高かった。出来上がったソースは lisp らしくないのかもしれないが、とりあえずはじめの一歩を記すことができた。以下、躓いたところを列挙。

  • 本みて理解しているつもりでも、cons,list,push が解ってなかった。目的をもってREPLで試すと少し理解が深まった。
  • どの言語もそうだけれど、1バイト単位の処理方法に意外と苦労する。今回は element-type,read-byte,code-char,char-code の組み合わせかな。
  • while はマクロで実現されているので、自分でマクロを組まなければいけないらしい(初心者には荷が重いので loop に書き換えた)。
  • return は、break のようなもので、二重ループを一気に抜け出たりはしてくれないらしい。
  • format は、独特な世界観で、なかなか覚えられない。そもそもlisp は関数の名前が長めのが多い。
出来上がってみれば、他の言語同様の構造で(lispらしくない?)どこに詰まったのかと思うところが悲しい。
(defun hdmp(adr line len)
  (format t "~8,'0x: " adr)
  (mapc (lambda(c) (format t "~2,'0x " c)) (reverse line))
  (setq zan (- 16 len))
  (if (> zan 0)
      (dotimes(i zan) (princ "   "))))

(defun cdmp(adr line len)
  (princ "| ")
  (mapc (lambda(c)
          (if (or (< c 32) (>= c 127))
              (format t ".")
              (format t "~a" (code-char c))))
        (reverse line))
  (setq zan (- 16 len))
  (if (> zan 0)
      (dotimes(i zan) (princ " ")))
  (princ " |")
  (fresh-line))

(defun dump(name)
  (with-open-file (in name :direction :input :element-type 'unsigned-byte)
    (setq adr 0)
    (setq cnt 0)
    (setq line nil)
    (loop
       (setq c (read-byte in nil nil))
       (if (equal c nil) (return t))

       (if (> cnt 15)
           (progn
             (hdmp adr line cnt)
             (cdmp adr line cnt)
             (setq adr (+ adr cnt))
             (setq cnt 0)
             (setq line nil)))

       (push c line)
       (setq cnt (1+ cnt)))
    (if (> cnt 0)
        (progn
          (hdmp adr line cnt)
          (cdmp adr line cnt))))

2013年5月22日水曜日

ruby で mysql 接続

ruby では、java でうまく行かなかった time 型の最大値も問題なく表示されたが指数表記に差異が見られた。原因はここに記載されているデフォルトのフォーマットが異なるのだろう。また、bit 型の表記は、mysql コマンドで表示させた時と同じサイコロ状の表記となった。(サイコロ状表記についてはこちら

タイプ DB設定値 ruby取込値
BIT(8) 1 mysql の表記と同じ
TINYINT 127 127
BOOL 1 1
SMALLINT 32767 32767
MEDIUMINT 8388607 8388607
INT 2147483647 2147483647
BIGINT 9223372036854775807 9223372036854775807
FLOAT 3.402823466E+38 3.40282e38
DOUBLE 1.7976931348623157E+308 1.7976931348623157e308
DECIMAL 1 1
DATE '9999-12-31' 9999-12-31
DATETIME '9999-12-3123:59:59' 9999-12-31 23:59:59
TIMESTAMP '2037-12-3123:59:59' 2037-12-31 23:59:59
TIME '838:59:59' 23:59:59
YEAR 2155 2155
CHAR 'a' a
VARCHAR(255) 'ab1' ab1
BINARY(255),@ 'ab2' ab2
VARBINARY(255) 'ab3' ab3
TINYBLOB 'ab4' ab4
TINYTEXT 'ab5' ab5
BLOB(255) 'ab6' ab6
TEXT(255) 'ab7' ab7
MEDIUMBLOB 'ab8' ab8
MEDIUMTEXT 'ab9' ab9
LONGBLOB 'abA' abA
LONGTEXT 'abB' abB
ENUM('a','b','c'), 'c' c
SET('e','f','g') 'ef' e,f

#! /home/naoki/.rvm/rubies/ruby-1.8.7-p371/bin/ruby
# coding: utf-8
require 'rubygems'
require 'mysql'
con = Mysql::new("127.0.0.1","user","password","db")

begin
  res = con.query("select * from test01")
  res.each do |row|
    puts row[0]
    puts row[1]
    puts row[2]
    puts row[3]
    puts row[4]
    puts row[5]
    puts row[6]
    puts row[7]
    puts row[8]
    puts row[9]
    puts row[10]
    puts row[11]
    puts row[12]
    puts row[13]
    puts row[14]
    puts row[15]
    puts row[16]
    puts row[17]
    puts row[18]
    puts row[19]
    puts row[20]
    puts row[21]
    puts row[22]
    puts row[23]
    puts row[24]
    puts row[25]
    puts row[26]
    puts row[27]
    puts row[28]
  end
ensure
  con.close
end

php でmysql接続

php では、java でうまく行かなかった time 型の最大値も問題なく表示されたが指数表記に差異が見られた。原因はここに記載されているデフォルトのフォーマットが異なるのだろう。また、bit 型の表記は、mysql コマンドで表示させた時と同じサイコロ状の表記となった。(サイコロ状表記についてはこちら

タイプ DB設定値 php取込値
BIT(8) 1
TINYINT 127 127
BOOL 1 1
SMALLINT 32767 32767
MEDIUMINT 8388607 8388607
INT 2147483647 2147483647
BIGINT 9223372036854775807 9223372036854775807
FLOAT 3.402823466E+38 3.40282e38
DOUBLE 1.7976931348623157E+308 1.7976931348623157e308
DECIMAL 1 1
DATE '9999-12-31' 9999-12-31
DATETIME '9999-12-3123:59:59' 9999-12-31 23:59:59
TIMESTAMP '2037-12-3123:59:59' 2037-12-31 23:59:59
TIME '838:59:59' 23:59:59
YEAR 2155 2155
CHAR 'a' a
VARCHAR(255) 'ab1' ab1
BINARY(255),@ 'ab2' ab2
VARBINARY(255) 'ab3' ab3
TINYBLOB 'ab4' ab4
TINYTEXT 'ab5' ab5
BLOB(255) 'ab6' ab6
TEXT(255) 'ab7' ab7
MEDIUMBLOB 'ab8' ab8
MEDIUMTEXT 'ab9' ab9
LONGBLOB 'abA' abA
LONGTEXT 'abB' abB
ENUM('a','b','c'), 'c' c
SET('e','f','g') 'ef' e,f

#! /usr/bin/php

perl で mysql 接続

perl では、java でうまく行かなかった time 型の最大値も問題なく表示されたが指数表記に差異が見られた。原因はここに記載されているデフォルトのフォーマットが異なるのだろう。また、bit 型の表記は、mysql コマンドで表示させた時と同じサイコロ状の表記となった。(サイコロ状表記についてはこちら

タイプ DB設定値 perl取込値
BIT(8) 1 mysqlと同じ表記
TINYINT 127 127
BOOL 1 1
SMALLINT 32767 32767
MEDIUMINT 8388607 8388607
INT 2147483647 2147483647
BIGINT 9223372036854775807 9223372036854775807
FLOAT 3.402823466E+38 3.40282e38
DOUBLE 1.7976931348623157E+308 1.7976931348623157e308
DECIMAL 1 1
DATE '9999-12-31' 9999-12-31
DATETIME '9999-12-3123:59:59' 9999-12-31 23:59:59
TIMESTAMP '2037-12-3123:59:59' 2037-12-31 23:59:59
TIME '838:59:59' 23:59:59
YEAR 2155 2155
CHAR 'a' a
VARCHAR(255) 'ab1' ab1
BINARY(255), 'ab2' ab2
VARBINARY(255) 'ab3' ab3
TINYBLOB 'ab4' ab4
TINYTEXT 'ab5' ab5
BLOB(255) 'ab6' ab6
TEXT(255) 'ab7' ab7
MEDIUMBLOB 'ab8' ab8
MEDIUMTEXT 'ab9' ab9
LONGBLOB 'abA' abA
LONGTEXT 'abB' abB
ENUM('a','b','c'), 'c' c
SET('e','f','g') 'ef' e,f

#! /usr/bin/perl
use DBI;

$d = "DBI:mysql:naoki:localhost";

$dbh = DBI->gtconnect($d,"user","password");
if (!$dbh) {
    printf("接続失敗\n");
    exit 1;
}
$sth = $dbh->gtprepare("select * from test01");
if (!$sth->gtexecute) {
    printf("SQL失敗\n");
    exit 1;
}
#$types = $sth->gt{TYPE};
#foreach $line (@$types) {
#  printf("[%d]\n",$line);
#}

while(@rec = $sth->gtfetchrow_array) {
    print @rec[0] . "\n";
    print @rec[1] . "\n";
    print @rec[2] . "\n";
    print @rec[3] . "\n";
    print @rec[4] . "\n";
    print @rec[5] . "\n";
    print @rec[6] . "\n";
    print @rec[7] . "\n";
    print @rec[8] . "\n";
    print @rec[9] . "\n";
    print @rec[10] . "\n";
    print @rec[11] . "\n";
    print @rec[12] . "\n";
    print @rec[13] . "\n";
    print @rec[14] . "\n";
    print @rec[15] . "\n";
    print @rec[16] . "\n";
    print @rec[17] . "\n";
    print @rec[18] . "\n";
    print @rec[19] . "\n";
    print @rec[20] . "\n";
    print @rec[21] . "\n";
    print @rec[22] . "\n";
    print @rec[23] . "\n";
    print @rec[24] . "\n";
    print @rec[25] . "\n";
    print @rec[26] . "\n";
    print @rec[27] . "\n";
    print @rec[28] . "\n";
}

$sth->gtfinish;
$dbh->gtdisconnect;

python で mysql 接続

python では、java でうまく行かなかった time 型の最大値も問題なく表示されたが、指数表記に差異が見られた。原因はここに記載されているデフォルトのフォーマットが異なるのだろう。また、bit 型の表記は、mysql コマンドで表示させた時と同じサイコロ状の表記となった。(サイコロ状表記についてはこちら

タイプ DB設定値 python取込値
BIT(8) 1 mysqlと同じ表記
TINYINT 127 127
BOOL 1 1
SMALLINT 32767 32767
MEDIUMINT 8388607 8388607
INT 2147483647 2147483647
BIGINT 9223372036854775807 9223372036854775807
FLOAT 3.402823466E+38 3.40282e+38
DOUBLE 1.7976931348623157E+308 1.79769313486e+308
DECIMAL 1 1
DATE '9999-12-31' 9999-12-31
DATETIME '9999-12-3123:59:59' 9999-12-31 23:59:59
TIMESTAMP '2037-12-3123:59:59' 2037-12-31 23:59:59
TIME '838:59:59' 838:59:59
YEAR 2155 2155
CHAR 'a' a
VARCHAR(255) 'ab1' ab1
BINARY(255),@ 'ab2' ab2
VARBINARY(255) 'ab3' ab3
TINYBLOB 'ab4' ab4
TINYTEXT 'ab5' ab5
BLOB(255) 'ab6' ab6
TEXT(255) 'ab7' ab7
MEDIUMBLOB 'ab8' ab8
MEDIUMTEXT 'ab9' ab9
LONGBLOB 'abA' abA
LONGTEXT 'abB' abB
ENUM('a','b','c'), 'c' c
SET('e','f','g') 'ef' e,f

#! /usr/bin/python
# -*- coding: utf-8 -*-

import MySQLdb

if __name__ == "__main__":

    connector = MySQLdb.connect(host="192.168.11.100",db="naoki",user="naoki",passwd="naoki",charset="utf8")
    cursor = connector.cursor()
    cursor.execute("select * from test01")

    result = cursor.fetchall()

    for row in result:
        print "===== Hit! ====="
        print row[0]
        print row[1]
        print row[2]
        print row[3]
        print row[4]
        print row[5]
        print row[6]
        print row[7]
        print row[8]
        print row[9]
        print row[10]
        print row[11]
        print row[12]
        print row[13]
        print row[14]
        print row[15]
        print row[16]
        print row[17]
        print row[18]
        print row[19]
        print row[20]
        print row[21]
        print row[22]
        print row[23]
        print row[24]
        print row[25]
        print row[26]
        print row[27]
        print row[28]

    cursor.close()
    connector.close()

java で mysql接続

java から mysql に接続してみた。TIMEの上限値が取得できない障害に出会ったが、24時間以内であれば問題はなかった。また、指数表記に差異が見られたが原因はここに記載されているデフォルトのフォーマットが異なるのだろう。bit 型の表記は、mysql コマンドで表示させた時と同じサイコロ状の表記となった。(サイコロ状表記についてはこちら

タイプ DB設定値 Java取込値
BIT(8) 3 3
TINYINT 127 127
BOOL 1 1
SMALLINT 32767 32767
MEDIUMINT 8388607 8388607
INT 2147483647 2147483647
BIGINT 9223372036854775807 9223372036854775807
FLOAT 3.402823466E+38 3.40282e38
DOUBLE 1.7976931348623157E+308 1.7976931348623157e308
DECIMAL 1 1
DATE '9999-12-31' 9999-12-31
DATETIME '9999-12-3123:59:59' 9999-12-31 23:59:59.0
TIMESTAMP '2037-12-3123:59:59' 2037-12-31 23:59:59.0
TIME '838:59:59' ×
YEAR 2155 2155-01-01
CHAR 'a' a
VARCHAR(255) 'ab1' ab1
BINARY(255),@ 'ab2' ab2
VARBINARY(255) 'ab3' ab3
TINYBLOB 'ab4' ab4
TINYTEXT 'ab5' ab5
BLOB(255) 'ab6' ab6
TEXT(255) 'ab7' ab7
MEDIUMBLOB 'ab8' ab8
MEDIUMTEXT 'ab9' ab9
LONGBLOB 'abA' abA
LONGTEXT 'abB' abB
ENUM('a','b','c'), 'c' c
SET('e','f','g') 'ef' e,f

import java.sql.*;
import java.lang.Long;

public class test11 {
  public static void main(String[] args) {
        String msg = "";
        try {
            // ドライバロード
            Class.forName("org.gjt.mm.mysql.Driver");

            // MySQLに接続
            Connection con = DriverManager.getConnection(
                        "jdbc:mysql://localhost/naoki", "user", "password");

            // ステートメント生成
            Statement stmt = con.createStatement();

            // SQLを実行
            String sqlStr = "SELECT * FROM test01";
            ResultSet rs = stmt.executeQuery(sqlStr);

            // 結果行をループ
            while(rs.next()){
                // レコードの値
                System.out.println(rs.getString("col01"));
                System.out.println(rs.getString("col02"));
                System.out.println(rs.getString("col03"));
                System.out.println(rs.getString("col04"));
                System.out.println(rs.getString("col05"));
                System.out.println(rs.getString("col06"));
                System.out.println(rs.getString("col07"));
                System.out.println(rs.getString("col08"));
                System.out.println(rs.getString("col09"));
                System.out.println(rs.getString("col10"));
                System.out.println(rs.getString("col11"));
                System.out.println(rs.getString("col12"));
                System.out.println(rs.getString("col13"));
                System.out.println(rs.getString("col14"));
                System.out.println(rs.getString("col15"));
                System.out.println(rs.getString("col16"));
                System.out.println(rs.getString("col17"));
                System.out.println(rs.getString("col18"));
                System.out.println(rs.getString("col19"));
                System.out.println(rs.getString("col20"));
                System.out.println(rs.getString("col21"));
                System.out.println(rs.getString("col22"));
                System.out.println(rs.getString("col23"));
                System.out.println(rs.getString("col24"));
                System.out.println(rs.getString("col25"));
                System.out.println(rs.getString("col26"));
                System.out.println(rs.getString("col27"));
                System.out.println(rs.getString("col28"));
                System.out.println(rs.getString("col29"));
            }

            // 接続を閉じる
            rs.close();
            stmt.close();
            con.close();
        }
        catch (ClassNotFoundException e){
            msg = "ドライバのロードに失敗しました";
            System.out.println(msg);
        }
        catch (SQLException e) {
            msg = "SQLに失敗しました";
            System.out.println(msg);
            e.printStackTrace();
        }
    }
}

2013年5月11日土曜日

mysql の bit 型のサイコロ表記の謎

mysql の bit 型を pythonやruby で出力すると、サイコロの4つ目のような表示になる。あまり見かけない表示だなと思いつつ、ふと、プログラムではどのように使うのか疑問に思った。


まずは、なんの加工もなしにダイレクトにプログラムに渡ってきているなら、ビットマスクできるのではないかと考えて抽出対象ビットを16進数と&してみたが、0が帰ってきた。


サイコロの4つ目のような表示になるのだから変なコードになっているのかと思い、ファイルに出力して16進ダンプしてみると設定した通りの値'0x01' が入っていた。


いい年をしてなんだが、0x01 を画面に出力するとサイコロの4つ目表示になるのか試してみた。確かにサイコロの4つ目表示が出てきた。


脇道にそれるがこのサイコロの4つ目表示は、ビット表記なのか16進表記なのか確かめてみると、16進表記っぽいが、16進全部が表記できるわけでもないらしい(年甲斐もないが。。)


本題にもどるがここまで来て、プログラム内でこのbit 型を使うときは unpack して数値にしてから、ビット操作するのだと気がついた。

binary 型や blob 型のように無変換のレアなままの値を保持している型の値をプログラムで利用しようとおもったら、同じように unpack を駆使することになるのだろう。

ちなみに、型のない言語で変数に保存したこれらの値の取り扱い方法は、プログラム依存になるしかないのだろうか・・・・(年甲斐もないな)

2013年5月10日金曜日

エクセルからmysqlに接続

excel の使い所は種々あるだろうが、その多くは各種DBやログを利用した解析やレポート作成ではないだろうか。それには最初に何らかの方法でデータベースからデータをエクセルまで運んでこなければならない。テキストやCSVをデータベースに見立ててODBC接続する方法なども考えられるが、出来れば直接データベースにアクセスして各種条件で抽出したデータをレポートとして利用したい。そこで、非常に普及している mysql に ado 接続してみることにした。

ubuntu 上の mysql を他のwindows から参照可能にする。
  1. my.cnf のローカルのみ接続を解除する。
    #bind-address = 127.0.0.1
    
      
  2. 接続許可ユーザとマシンのIPを登録、確認。
    mysql> grant all privileges on *.* to ユーザ名@外部ホストIP identified by 'パスワード' with grant option;
    mysql> flush privileges;
    mysql> select user from mysql.user
    
      
  3.  mysql のリスタート
    $ sudo /etc/init.d/mysql restart
    
      
windows 上で mysql 接続の準備をする。
  1.  ドライバを以下よりダウンロードする。
    Download Connector/ODBC

  2.  ユーザDSNに接続定義する。
mysql と excel の型を比較する。
  1.  以下のコードで接続する。(エラーを起こす型を取り除いた)
    Sub test01()
        Dim con As ADODB.Connection
        Dim rs  As ADODB.Recordset
        
        Dim cntString As String
        Dim sqlStr As String
        
        Dim rowNo As Integer
        Dim colno As Integer
        Dim item As Variant
        
        cntString = "Driver={MySQL ODBC 5.1 DRIVER};" _
                & "SERVER=192.168.11.100;" _
                & "DATABASE=naoki;" _
                & "USER=naoki;" _
                & "PASSWORD=naoki;"
        
        Set con = New ADODB.Connection
        
        On Error GoTo Err
        
        con.Open cntString
        
        sqlStr = "select col02,col03,col04,col05,col06,col07,col08,col09,col10,col11,col12,col13,col15,col16,col17,col21,col23,col25,col27,col28,col29 from test01"
        
        Set rs = con.Execute(sqlStr)
        
        Worksheets("Sheet2").Cells.Clear
        
        rowNo = 1
        colno = 1
        
        Do While rs.EOF = False
            For Each item In rs.Fields
                Worksheets("Sheet2").Cells(rowNo, colno).Value = item.Value
                colno = colno + 1
            Next
            colno = 1
            rowNo = rowNo + 1
            
            rs.MoveNext
        Loop
        
        con.Close
        Set rs = Nothing
        Set con = Nothing
        
    Exit Sub
    
    Err:
        Set rs = Nothing
        Set con = Nothing
        MsgBox (Err.Description)
    End Sub
      
  2.  データベース設定値と取込み結果の比較

    タイプ DB設定値 エクセル取込値
    BIT(8) 1 ×
    TINYINT 127 127
    BOOL 1 1
    SMALLINT 32767 32767
    MEDIUMINT 8388607 8388607
    INT 2147483647 2147483647
    BIGINT 9223372036854775807 9.22337E+18
    FLOAT 3.402823466E+38 3.40282E+38
    DOUBLE 1.7976931348623157E+308 1.7977E+308
    DECIMAL 1 1
    DATE '9999-12-31' 9999/12/31
    DATETIME '9999-12-3123:59:59' 9999/12/3123:59
    TIMESTAMP '2037-12-3123:59:59' 2037/12/3123:59
    TIME '838:59:59' ×
    YEAR 2155 2155
    CHAR 'a' a
    VARCHAR(255) 'ab1' ab1
    BINARY(255),@ 'ab2' ×
    VARBINARY(255) 'ab3' ×
    TINYBLOB 'ab4' ×
    TINYTEXT 'ab5' ab5
    BLOB(255) 'ab6' ×
    TEXT(255) 'ab7' ab7
    MEDIUMBLOB 'ab8' ×
    MEDIUMTEXT 'ab9' ab9
    LONGBLOB 'abA' ×
    LONGTEXT 'abB' abB
    ENUM('a','b','c'), 'c' c
    SET('e','f','g') 'ef' e,f

2013年5月9日木曜日

エクセルでもクラス風味

エクセルVBAの本はどうして分厚くて、高くて、役に立たないのだろう。よんでも、例文を入力して実行してみても一向にわかった気がしないし、アプリが作れるような気にもならない。

まず、なぜオブジェクト指向っぽい体系なのにそれがあまり語られないのであろう。また、例文やクラスの利用方法を示していても、全てを網羅しているわけでもないのにオブジェクトブラウザとヘルプなどでの当たりの付け方などに言及されないのはなぜなのだろう。エクセルはパソコンを職業とする人以外の人たちも多数利用し、プログラマでもないのに結構使いこなしている方を見かけるのだが、よほど先入観がないか、優れた人達なのではないだろうか。

そんな一般な人たちに脅威を抱きつつ、テキスト貼り付けマクロのコードの見直しとクラス風味への変更を行なってみた。本と首っ引きで作成したのが前回のもので、今回はオブジェクトブラウザとヘルプ、及び、マクロの記録を使ってコードを書きなおしてみた。かなり短くなってしまったが、やりたかったイメージはこちらの方が近いと思う。クラス風味にすることで、他のエクセルのライブラリへの理解も深まろうというものです。しかし、作るのに時間がかかるなぁ。頭悪すぎを実感します。

呼び出しマクロ
Sub test()
    Dim List As New TextListing
    
    With List
        .PathName = ThisWorkbook.Path
        .TextListing
    End With
End Sub
クラス風味のコード
Public PathName As String

Sub TextListing()
    Dim temp As Workbook
    Dim fname As String

    'テキストファイルにマッチングするよう指定
    fname = Dir(PathName & "\*.txt")
    Do While fname <> ""
        '指定のファイルを新しいブックに読み込む
        Set temp = Workbooks.Open(Filename:=PathName & "\" & fname,Format:=5)
        
        'フォントサイズを9ポイント
        temp.Worksheets(1).Cells.Font.Size = 9
        
        'フォントを HGゴシックE に変更
        temp.Worksheets(1).Cells.Font.Name = "HGゴシックE"
        
        '枠線の消去
        ActiveWindow.DisplayGridlines = False
        
        '読み込んだシートをマクロを起動したブックに移動
        temp.Worksheets(1).Move Before:=ThisWorkbook.Sheets(1)
        
        '次のファイル名を取得
        fname = Dir
    Loop
End Sub

2013年5月6日月曜日

エクセルのテキスト貼り付けマクロ

テキストのテストエビデンスなどをパソコンではオフィスなどしか触ったことのない人に見せる場合、エクセルに貼り付けて送付したりするという事がよくあった。大量にある場合はエクセルの得意な方に、テキストをシートに貼り付けるマクロを書いてもらって対処したりしていたが、環境が変わるたびに作ってもらえる人を探すのも不毛なので自分で作ってみることにした。

unix 側で取得したテキストエビデンスをPCに移動し、そのエビデンスのフォルダにマクロを仕掛けたエクセルファイルを放り込んでマクロを起動すると、全テキストファイルをファイル毎に1シートにして一つのブックにするものである。

今回は、java のソースのsdiff の結果を sjis にコード変換したのちタブをスペースに置き換えて利用した。
$ sdiff test01.java test02.java | nkf -s | expand -8 > ../excel/test01-02.txt
$ sdiff test02.java test03.java | nkf -s | expand -8 > ../excel/test02-03.txt
$ sdiff test03.java test04.java | nkf -s | expand -8 > ../excel/test03-04.txt

マクロを起動結果。


ソースコード
Sub Macro1()
    Dim myPath As String
    Dim myFileName As String
   
    '新規ブックの作成
    Dim myWb As Workbook
    Set myWb = Workbooks.Add
  
    '指定ディレクトリのファイルを順番にシートに貼り付け
    myPath = ThisWorkbook.Path & "\"
    myFileName = Dir(myPath, 0)
    Do While Len(myFileName) > 0
        ' テキストファイルの場合シート作成
        If Right(myFileName, 3) = "txt" Then
            MakeSheet file:=myFileName, sheet:=myWb
        End If
        Debug.Print myPath & myFileName
        myFileName = Dir()
    Loop
End Sub

Sub MakeSheet(file As String, sheet As Workbook)
    Dim myFso As Object
    Dim myFileName As String
    Dim myStr As String
    Dim cnt As Long
    Dim mySht As Worksheet
    Set myFso = CreateObject("Scripting.FileSystemObject")
    '
    ' 新しいシートを追加
    Set mySht = Worksheets.Add(after:=Sheets(Sheets.Count))
    mySht.Name = file
    
    'シート全体を選択してフォントを設定
    Cells.Select
    mySht.Cells.Font.Size = 10
    mySht.Cells.Font.Name = "HGゴシックM"
    
    '罫線を削除
    Cells.Select
    ActiveWindow.DisplayGridlines = False
    
    'ファイル名を設定
    myFileName = ThisWorkbook.Path & "\" & file
    
    '一行ずつ読み込み、シートに文字列として貼り付け
    cnt = 1
    With myFso.OpenTextFile(myFileName, 1)
        Do Until .AtEndOfStream
            myStr = .ReadLine
            Debug.Print myStr
            With Cells(cnt, 1)
                .NumberFormatLocal = "@"
                .Value = myStr
            End With
            cnt = cnt + 1
        Loop
        .Close
    End With
    
    ' ワークシートを指定ブックに移動
    mySht.Move before:=sheet.Sheets(1)
    
    Set mytxt = Nothing
    Set myFso = Nothing
    Set mySht = Nothing
End Sub