2012年12月23日日曜日

Excel罫線のオートフィルタの問題点

Excel VBA で描いた罫線で オートフィルタ を使ったとき。フィルタ結果の一部に「 本来表示されるべきではない罫線が表示される現象 」が発生していました。

なかなか解決策が見つからず、この対策としては「 フィルタ結果に対して罫線を再描画する 」といった、場当たり的な方法でやり繰りしていたのですが、ようやく解決策が見つかりました。



「 本来表示されるべきではない罫線、が表示される現象 」とは

ここで改めて、この現象の説明をしておきます。下の図は VBA で罫線を描いた表のオートフィルタ前の状態です。表中で LineColor 列の red 行のデータ red を赤い下罫線、 blue 行のデータ blue を青い下罫線で描いています。

つぎに、オートフィルタを使って LineColor 列の、 red を選択した場合のフィルタ結果が下図です。期待する正しい結果は、赤い下罫線だけの表示なのですが、この表示結果では関係のない所に青い罫線が表示されていたり、赤い罫線のはずの red の所が青い罫線になっており、フィルタ結果がみっともない状態です。

オートフィルタで LineColor 列の、 blue を選択した場合も同様です。


スタイル設定を調べたときにヒントが!

Excel VBA の HELP で、 Bordersオブジェクト を調べると、こんな説明になっています。

このことから下罫線を描く場合には、 Bordersオブジェクト に指定する XlBordersIndex クラス の定数から、 xlEdgeBottom を使って描いていました。

以前、「 スタイル設定をシートに出力する VBA マクロ 」を作りました。このとき Stylesコレクション から取得した、 Bordersプロパティ indexの値 は以下のものでした。

xlLeft, xlRight, xlTop, xlBottom, xlDiagonalDown, xlDiagonalUp

Excel VBA の HELP、 Stylesコレクション のサンプルコードにも xlTop が使われていました。

HELP の Itemプロパティ では、「 xlEdgeXXX 」を使うように書かれています。

さて、ここで疑問が湧き出します。上下左右の罫線にある、「 xlEdgeXXX 」と「 xlXXX 」の定数の違いは何なのでしょうか?



「 xlEdgeBottom 」と「 xlBottom 」を比較してみる

両者の違いを探るため、比較用の VBA マクロを作り調べてみました。(この VBA マクロは文末に記載しています。)

テスト環境は、Excel 2003 SP3・Windows XP SP3 です。

下図左側の下罫線は「 xlEdgeBottom 」、下図右側の下罫線は「 xlBottom 」を使って描いています。その他は同一内容です。

オートフィルタで LineColor 列の、 red を選択したものです。下図右側の「 xlBottom 」の表示が良い感じです。

オートフィルタで LineColor 列の、 blue を選択。こちらの表示結果でも、下図右側の「 xlBottom 」で描いたほうは、正しくフィルタ表示できています。


オートフィルタでは「 xlBottom 」なら OK なの?

そこで、他のバージョンの Excel でも大丈夫なのか調べてみました。

他に使用できる Excel は、

  • Excel 2000 SP3
  • Excel 2010 評価版 (Office Professional 2010 Trial)
  • Excel 2013 Preview (Microsoft Office Professional 2013 Preview)
の 3 種類です。

まずはじめに Excel 2000 SP3・Windows XP SP3 から試してみました。

オートフィルタ項目 red

オートフィルタ項目 blue


つづいて、Excel 2010 評価版・Windows 7 Enterprise 評価版です。

オートフィルタ項目 red

オートフィルタ項目 blue


最後は Excel 2013 Preview・Windows 8 Release Previewです。

オートフィルタ項目 red

オートフィルタ項目 blue


結論、オートフィルタでは「 xlBottom 」を使えば OK

下罫線に「 xlBottom 」を使ったほうでは、いずれの結果もうまく動作しています。これでオートフィルタには「 xlBottom 」を使うことで正しく表示できることがわかりました。

今回調査した結果と、 Web で調べた結果から xlEdgeXXX と xlXXX の違いについて纏めてみると。(内容には未確認部分も含んでいます。)

  • ひとつのセルの上・下・左・右の罫線指定には、それぞれ 「 xlTop 」, 「 xlBottom 」, 「 xlLeft 」, 「 xlRight 」の定数を使う。
  • セル範囲(外周)の上・下・左・右の罫線指定には、それぞれ 「 xlEdgeTop 」, 「 xlEdgeBottom 」, 「 xlEdgeLeft 」, 「 xlEdgeRight 」 の定数を使う。

オートフィルタを使わなければ、どちらの方法で描いても大して変わらないのですが、オートフィルタを使うと挙動が違ってくるという訳です。これがオートフィルタの仕様なのか、バグなのか良く判りませんが、今まで懸案だった問題が少しスッキリした感じです。

今回の調査に使った VBA マクロを以下に記載します

Option Explicit
'/////  罫線のオートフィルタ動作テスト、メイン  /////
Sub Test_Borders()
    Dim mysheet As Worksheet
    Dim rTable_tmp As Range, rTable_left As Range, rTable_right As Range
    Dim xVal As Long
    Const xTable_Width As Integer = 6
    Const xTable_Height As Integer = 19
    Dim sTable_tmp As Variant

On Error GoTo ERR
    '表示データセット
    sTable_tmp = Array(Array("LineColor", "    ", "    ", "    ", "    ", "    "), _
                            Array("red ", "red ", "red ", "    ", "    ", "    "), _
                            Array("blue", "    ", "    ", "    ", "blue", "blue"), _
                            Array("red ", "    ", "red ", "red ", "    ", "    "), _
                            Array("blue", "    ", "    ", "blue", "blue", "    "), _
                            Array("red ", "    ", "    ", "red ", "red ", "    "), _
                            Array("red ", "    ", "    ", "    ", "red ", "red "), _
                            Array("blue", "    ", "blue", "blue", "    ", "    "), _
                            Array("blue", "blue", "blue", "    ", "    ", "    "), _
                            Array("red ", "red ", "red ", "red ", "    ", "    "), _
                            Array("red ", "    ", "red ", "red ", "red ", "    "), _
                            Array("red ", "    ", "    ", "red ", "red ", "red "), _
                            Array("blue", "blue", "blue", "blue", "    ", "    "), _
                            Array("blue", "    ", "blue", "blue", "blue", "    "), _
                            Array("blue", "    ", "    ", "blue", "blue", "blue"), _
                            Array("red ", "red ", "red ", "red ", "red ", "    "), _
                            Array("blue", "    ", "blue", "blue", "blue", "blue"), _
                            Array("red ", "    ", "red ", "red ", "red ", "red "), _
                            Array("blue", "blue", "blue", "blue", "blue", "    "))
    Set mysheet = ActiveSheet
    Set rTable_left = mysheet.Range("A2")
    Set rTable_right = mysheet.Range("H2")
    
    'オートフィルタ解除
    If mysheet.AutoFilterMode = True Then
        mysheet.AutoFilterMode = False
    End If
    
    '領域を消去
    Call DeleteTable(Range("A1:M20"))
    
    'テーブル作成 (失敗する罫線 xlEdgeBottom)
    rTable_left.Offset(-1, 0).Value = "失敗する罫線"
    Call Write_Table(rTable_left, sTable_tmp, xTable_Height, xTable_Width)
    xVal = xlEdgeBottom
    Set rTable_tmp = rTable_left.Offset(1, 1).Resize(xTable_Height - 1, xTable_Width - 1)
    Call Draw_Borders(rTable_tmp, xVal)
    
    'テーブル作成 (成功する罫線 xlBottom)
    rTable_right.Offset(-1, 0).Value = "成功する罫線"
    Call Write_Table(rTable_right, sTable_tmp, xTable_Height, xTable_Width)
    xVal = xlBottom
    Set rTable_tmp = rTable_right.Offset(1, 1).Resize(xTable_Height - 1, xTable_Width - 1)
    Call Draw_Borders(rTable_tmp, xVal)

    'オートフィルタ オン
    If mysheet.AutoFilterMode = True Then
        mysheet.AutoFilterMode = False
    End If
    
    mysheet.Range("A2:M2").AutoFilter
    mysheet.Columns("A:M").AutoFit

ERR:
    Set rTable_right = Nothing
    Set rTable_left = Nothing
    Set rTable_tmp = Nothing
    Set mysheet = Nothing
End Sub
'/////  テーブルデータを表示  /////
Sub Write_Table(ByVal rTable_in As Range, ByVal sTable_in As Variant, nRow As Integer, nCol As Integer)
    Dim nCount As Integer, rTable As Range
    Set rTable = rTable_in.Resize(, nCol)
    
    For nCount = 0 To nRow - 1
        rTable.Offset(rowOffset:=nCount).Value = sTable_in(nCount)
    Next nCount

    Set rTable = Nothing
End Sub
'/////  テーブルに下罫線を描画  /////
Sub Draw_Borders(rTable As Range, xVal As Long)
    Dim r As Range

    '下罫線を描画
    For Each r In rTable
        With r.Borders(xVal)
            Select Case r.Text
            Case "red "
                .LineStyle = xlContinuous
                .Weight = xlThick
                .ColorIndex = 3
            Case "blue"
                .LineStyle = xlContinuous
                .Weight = xlThick
                .ColorIndex = 5
            Case Else
                .LineStyle = xlNone
            End Select
        End With
    Next r

    Set r = Nothing
End Sub

'/////  テーブルを消去  /////
Sub DeleteTable(rTable_range As Range)
    Dim r As Range
    rTable_range.Clear
    
    '下罫線を消去(消去は xlEdgeBottom を使う。)
    For Each r In rTable_range
        r.Borders(xlEdgeBottom).LineStyle = xlLineStyleNone
    Next r

    Set r = Nothing
End Sub

2012年12月4日火曜日

HDL-GS500を、1.0TBに換装して再初期化する。

今まで3回にわたって、HDL-GS500の故障からデータ救出までを書きました。

  1. HDL-GS500が故障。
  2. 壊れたHDDを、Advanced FormatのHDDに交換。
  3. GNU ddrescueを使って、壊れたHDDからデーターを救出。
救出データのバックアップが終わりましたので、今回はHDL-GS500を再初期化しました。
これで1.0TBのHDL-GS500になりました。


再初期化の前にtar2diskを一部修正

データ救出用として暫定修正していたtar2diskを、通常使用できるように修正しました。

  • disk2cyl( )は、データ救出のために500GBに固定していた設定を解除。ディスクのセクター数からモデルを自動識別するように修正。セクターの計算式を見直し、遠回りしていた計算をシンプルにしました。
  • partition( )は、全てのパーティションの開始位置を、アライメント調整した値に修正しました。

修正版tar2disk再初期化用

#!/bin/sh
#
# tar2disk: tar ball をディスクに展開
#
# usage: tar2disk sda
#///// 2012/10/01   sfdiskをシリンダ指定から、セクタ指定へ変更。/////
#///// 2012/11/06   全パーティションのアライメント調整。/////
mnt=./mnt
sddev=/dev/hdb   # ##### 初期化する環境に合わせて変更してください #####

PATH=$PATH:/sbin

#
# 16進->10進変換
#
hex2dec() {
    expr 1 + `printf "%d" $1`
}

#
# モデルごとの制限セクタ数
#
sector160=`hex2dec 0x12A05FBF`
sector250=`hex2dec 0x1D1A9C7F`
sector300=`hex2dec 0x22ECB57F`
sector320=`hex2dec 0x2540BF7F`
sector400=`hex2dec 0x2E90F73F`
sector500=`hex2dec 0x3A353900`
sector750=`hex2dec 0x574FCD9F`
sector1000=`hex2dec 0x74706DAF`

#cyl_end=379        # sda5 の終了セクタ
cyl_end=6088641     #/////シリンダ値をセクタ値に変更/////

#
# ディスク名からモデルで丸められたセクタ数を得る
#///// 2012/10/01   セクタ数を返すように修正 /////
#///// 2012/11/06   修復時の500GB固定を解除、計算式最適化。/////
disk2cyl() {
    local disk=$1
    local sector=`cat /sys/block/$disk/size`
#/////    local sector=976566529    /////
    if [ $sector -lt $sector160 ]; then
        echo -n error
        exit 1
    elif [ $sector -lt $sector250 ]; then
        expr $sector160 - $cyl_end
    elif [ $sector -lt $sector300 ]; then
        expr $sector250 - $cyl_end
    elif [ $sector -lt $sector320 ]; then
        expr $sector300 - $cyl_end
    elif [ $sector -lt $sector400 ]; then
        expr $sector320 - $cyl_end
    elif [ $sector -lt $sector500 ]; then
        expr $sector400 - $cyl_end
    elif [ $sector -lt $sector750 ]; then
        expr $sector500 - $cyl_end
    elif [ $sector -lt $sector1000 ]; then
        expr $sector750 - $cyl_end
    else
        expr $sector1000 - $cyl_end
    fi
    return 0
}

#
# パーティションを切る
#///// 2012/10/01   シリンダ指定からセクタ指定へ変更 sda6の開始セクタは暫定値/////
#///// 2012/11/06   全パーティションのアライメント調整。/////
partition() {
 local disk=$1
 local c5=417687    # 26*255*63-2
 local cyl=`disk2cyl $disk`
 local ext=`expr $cyl + $c5 + 10`

 dd if=/dev/zero of=/dev/$disk bs=512 count=2 || exit 1
 sfdisk -f -uS /dev/$disk <<EOF || exit 1
2048,626536,L
628584,833328,L
1461912,4209032,S
5670944,$ext,E
5670952,$c5,L
6088640,$cyl,L
EOF
}


#
# format
#///// 2012/10/01 ブロックサイズを4096バイトに変更。/////
format() {
 local i=$1

 if [ $i -eq 1 ]; then
  [ $flag_reset -eq 1 ] && return 0
  mke2fs -b 4096 -j -m1 $sddev$i || return 1
 elif [ $i -eq 2 ]; then
  mke2fs -b 4096 -j -m1 $sddev$i || return 1
 elif [ $i -eq 5 ]; then
  mke2fs -b 4096 -j -N 100000 \
   -O dir_index,filetype,sparse_super $sddev$i || return 1
 else
  [ ! -f /sbin/mkfs.xfs ] && cp -a ${SCRIPT_PATH}/mkfs.xfs /sbin/
  mkfs.xfs -f $sddev$i || return 1
 fi
 return 0
}


#
# fw_install
#
fw_install() {
 touch verify_on_boot
 cp -a ../sd?.tgz ../tar2disk ./.landisk/
 mkdir ./.landisk/mnt
}


#
# 初期化後updateの為にflag fileをtouchする
#
set_reset_flag() {
 touch ./.landisk/reset_ok
}


#
# ディスクを 0 クリアする
#
sanitize_disk() {
 local i=$1
 echo "--- sanitize disk"
 dd if=/dev/zero of=$sddev$i bs=1M || return 1
}


#
# install_logを 作成する
#
set_install_log() {
 local end_time
 local j
 local mac_addr=`/sbin/ifconfig eth0 | sed -n 's/^.*HWaddr \([0-9A-F:]*\)[ ]*$/\1/p'`
 local log_dir="$mnt/factory_log"
 local install_log="$log_dir/install.log"

 mount ${sddev}5 $mnt || return 1
 if [ ! -d $log_dir ]; then
  mkdir $log_dir || return 1
 fi
 end_time=`date`
 echo "Mac Address: $mac_addr" > $install_log
 echo "Install Start: $START_TIME" >> $install_log
 echo "Install End: $end_time" >> $install_log
 for j in 1 2 3 4 5 6 7 8 9 10; do
  sync
  umount $mnt && break || sleep 1
 done
}

#
# factorylogの退避
#
bk_factory_log() {
 local factory_tgz=$topdir/factory_log.tar.gz
 if [ ! -f $factory_tgz ]; then
  mount ${sddev}5 $mnt || return 1
  tar cpzf $factory_tgz -C $mnt factory_log
  umount $mnt
 fi
}

#
# factorylogの書き戻し
#
restore_factory_log() {
 local factory_tgz=$topdir/factory_log.tar.gz
 if [ -f $factory_tgz ]; then
  tar xpzf $factory_tgz
  echo `LANG=C date`: reset_script: >> factory_log/powerlog
  rm -f $factory_tgz
 fi
}


#
# smartチェックを行う
#
smart_check() {
 local disk=$1
 local RESULT_SMARTCTL=0
 local RESULT_SMARTCTL_BIT0=0
 local RESULT_SMARTCTL_BIT1=0
 local RESULT_SMARTCTL_BIT2=0
 local RESULT_SMARTCTL_BIT3=0
 [ ! -f /usr/sbin/smartctl ] && cp -a ${SCRIPT_PATH}/smartctl /usr/sbin/

 /usr/sbin/smartctl --smart=on --offlineauto=on --saveauto=on \
     /dev/${disk}
 /usr/sbin/smartctl -a /dev/${disk}
 RESULT_SMARTCTL=$?
 RESULT_SMARTCTL_BIT0=$((${RESULT_SMARTCTL} & 1))
 RESULT_SMARTCTL_BIT1=$((${RESULT_SMARTCTL} & 2))
 RESULT_SMARTCTL_BIT2=$((${RESULT_SMARTCTL} & 4))
 RESULT_SMARTCTL_BIT3=$((${RESULT_SMARTCTL} & 8))

 if [ ${RESULT_SMARTCTL_BIT0} -ne 0 ]; then
     echo "*** FAILED TO ENABLE S.M.A.R.T. DISK=${disk} ***"
     echo "*** COMMAND LINE PARSE ERROR ***"
     return 1
 fi
 if [ ${RESULT_SMARTCTL_BIT1} -ne 0 ]; then
     echo "*** FAILED TO ENABLE S.M.A.R.T. DISK=${disk} ***"
     echo "*** DEVICE OPEN FAILED ***"
     return 1
 fi
 if [ ${RESULT_SMARTCTL_BIT2} -ne 0 ]; then
     echo "*** FAILED TO ENABLE S.M.A.R.T. DISK=${disk} ***"
     echo "*** S.M.A.R.T. COMMAND FAILED ***"
     return 1
 fi
 if [ ${RESULT_SMARTCTL_BIT3} -ne 0 ]; then
     echo "*** S.M.A.R.T ERROR DETECTED DISK=${disk} ***"
     echo "*** STATUS: DISK FAILING ***"
     return 1
 fi
 return 0
}


#
# メイン
#
disk=$1
mode=$2
topdir=`pwd`

if [ "$disk" = "" ]; then
 echo usage: tar2disk sda 1>&2
 exit -1
fi

if [ "x$mode" == "xreset" ]; then
 flag_install=0
 flag_reset=1
 flag_reset_full=0
elif [ "x$mode" == "xreset_full" ]; then
 flag_install=0
 flag_reset=1
 flag_reset_full=1
else
 flag_install=1
 flag_reset=0
 flag_reset_full=0
fi

for i in 1 2 5 6; do
 umount $sddev$i
done

if [ $flag_install -eq 1 ]; then
 smart_check $disk || exit 1
 partition $disk
fi

mkswap /dev/${disk}3
swapon /dev/${disk}3
trap "swapoff /dev/${disk}3" 0

for i in 1 2 5 6; do
 cd $topdir
    
 echo --- partitioning $i
 [ $i -eq 6 -a $flag_reset_full -eq 1 ] && sanitize_disk $i
 [ $i -eq 5 -a $flag_reset -eq 1 ] && bk_factory_log
 echo --- format partition
 format $i || exit 1
 mount $sddev$i $mnt || exit 1

 echo --- extracting tar ball
 cd $mnt || exit 1
 tar zxf ../sd$i.tgz || exit 1
 [ $i -eq 1 -a $flag_install -eq 1 ] && fw_install
 [ $i -eq 1 -a $flag_reset -eq 1 ] && set_reset_flag
 [ $i -eq 5 -a $flag_reset -eq 1 ] && restore_factory_log
 cd $topdir || exit 1
    
 echo --- unmounting
 for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
  sync
  umount $mnt && break || sleep 1
 done
 [ "$?" -ne 0 ] && exit 1
done

[ $flag_install -eq 1 ] && set_install_log
exit 0


作業の準備

バックアップが終わったHDL-GS500からHDDを取り出し、USB-SATA変換アダプタ経由でPCに接続しました。このとき間違いを避けるために、元々PCに搭載しているHDDの接続を取り外しておくと、とても安全に作業できます。

  • はじめる前にtar2diskの9行目は、初期化する環境に合わせて変更が必要です。
  • sddev=/dev/hdb   # ##### 初期化する環境に合わせて変更してください #####
    
  • 初期化するHDDのデバイス・ノードは、dmesgなどで確認します。
    例えば、/dev/sdcなら、9行目をsddev=/dev/sdcに変更します。
  • 再セットアップ用ファイルsd1.tgz, sd2.tgz, sd5.tgz, sd6.tgz, tar2diskが入ったUSBメモリ(1回目のときに保存したもの)は、tar2diskの内容を今回の修正版に変更しておきます。

HDDの再初期化

knoppix DVDを起動して端末を立ち上げsu -rootになります。

最初の状態として、

/dev/sdcには、再初期化するHDDが
/dev/sddには、USBメモリが
接続されている状態とします。

USBメモリを、マウントポイントを作成してマウントします。

# mkdir /media/usb
# mount /dev/sdd1 /media/usb

USBメモリのtar2diskを実行します。

# cd /media/usb/hdd1/.landisk
# ./tar2disk sdc
これでHDDが初期化されます。

シリアルコンソールから、sfdiskした結果です。HDDのセクターサイズをtar2diskが自動認識して、計算どおり1.0TBでパーティショニングできました。

# sfdisk -uS -l /dev/hdb

Disk /dev/hdb: 121601 cylinders, 255 heads, 63 sectors/track
Warning: extended partition does not start at a cylinder boundary.
DOS and Linux will interpret the contents differently.
Units = sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
/dev/hdb1          2048    628583     626536  83  Linux
/dev/hdb2        628584   1461911     833328  83  Linux
/dev/hdb3       1461912   5670943    4209032  82  Linux swap / Solaris
/dev/hdb4       5670944 1953525167 1947854224   5  Extended
/dev/hdb5       5670952   6088638     417687  83  Linux
/dev/hdb6       6088640 1953525166 1947436527  83  Linux

再初期化後にHDDに書き込まれたtar2diskは、9行目の修正部分を元のsddev=/dev/hdbに戻しておきます。HDL-GS500の内部から見たHDDのデバイス・ノードは/dev/hdbになっています。

sddev=/dev/hdb   # ##### 初期化する環境に合わせて変更してください #####
この作業を忘れると、Webメニューのシステム初期化を実行する場合に失敗します。

再初期化したHDDでは、第1パーティション(今回の状態ならsdc1)の.landiskディレクトリが、tar2diskの保存場所です。


作業完了

修正後にHDL-GS500を再組立すると作業完了です。

HDL-GS500の、1.0TB化が完了しました。



tar2diskのオプションについて

Webメニューのシステム初期化では、tar2diskに以下のオプションをつけて実行しているようです。

通常の初期化を行う場合

# ./tar2disk hdb reset

内蔵HDDの完全消去を行う場合は

# ./tar2disk hdb reset_full



最後に今回のトラブル談

HDL-GS500のトラブルが解決した後、作業用PCにトラブル発生。

.
.

その日の夜、言いようのない睡魔に襲われながら、再初期化の作業を始めていました。

エラーを出して途中で止まるtar2disk。

「何でやろぅ?おかしいなぁ…」

あまりにも眠たくて、考えようとしても全く頭が働かない。

何度も深い眠りの淵に引き込まれそうになりながら、作業を続けようとしていました。

「もうあかん、今日は無理や…」

とうとう睡魔に勝てず、その夜の作業は諦めて早々に寝ることに。


翌日の夕食後、おもむろに作業を再開。

原因を探るために、前日の作業ログを、以前のログと見比べる。

「何故だかpartitioning 1のinodesの数値が大きい?
Superblock backups stored on blocks:のブロックも多い???」

嫌な予感が…

--- partitioning 1
--- format partition
mke2fs 1.42.2 (9-Apr-2012)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
6561792 inodes, 26216064 blocks
262160 blocks (1.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=0
801 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
 4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

--- extracting tar ball
--- unmounting
--- partitioning 2
--- format partition
mke2fs 1.42.2 (9-Apr-2012)
mke2fs: Device size reported to be zero.  Invalid partition specified, or
 partition table wasn't reread after running fdisk, due to
 a modified partition being busy and in use.  You may need to reboot
 to re-read your partition table.

tar2diskを見直して、ようやく原因に気づく。

「えぇ~っ、」

「やってしもた~」

諦めの妖精と、執着の妖精たちが、頭の中で踊りだしていました。



少し時間をおいてから、昨晩の様子を思い返すと。

作業PCのHDDを取り外さずに、USB-SATA変換アダプタ経由で、再初期化用のHDDをPCに接続していました。

そして、9行目の修正を忘れて、前の作業のときに設定していたsdaのままで実行。

sddev=/dev/sda   # ##### 初期化する環境に合わせて変更してください #####

つまり、USB-HDDではなく作業用PC のCドライブに書き込んでいたのです。

シェルスクリプトは、指示されたとおりにCドライブをext3でフォーマット後、tarボールを展開していました。その結果、作業PC のCドライブを飛ばしてしまったのでした。

「Windowsが立ち上がらない。困った!」

もう後の祭りです。


ほとんどのファイルは、別ドライブにバックアップを取ったつもりでしたが。マイドキュメントのバックアップが、あまり出来ていなかったことがわかりました。

そのため、データ救出、WindowsXPの再インストール、アプリケーションのインストール、嵐のようなアップデートと再起動の繰り返し等。余計な用事がいっぱい増えてしまい、今まで手間取っていました。

データの救出にはTestDiskPhotoRecを使いました。ほとんどのデジカメ画像が救出できましたが、長年可愛がってきたExcelファイルを幾つか失いました。 残念 X(

「気をつけよう、眠たい時のPC作業」