TIL

Today I Learned. 知ったこと、学んだことを書いていく

ADOでExcelファイルを読み込んだ時に文字列がNullになってしまうときの対処法 - VBA

結論

Extended PropertiesIMEX=1を追加する!

解説

Excelファイルを読み込むとき、1行目がヘッダーで2行目以降がデータである場合、そのままデータベースとして読み込むことができるため、すごい便利。

でも、仕様バグでしっかりとデータが存在するにもかかわらず、Nullとして読み込まれてしまうことがあるらしい。

これは、Excelの上位8行を読み込んでその列の一番多い型でデータを読み込むようになっているため、おこってしまうらしい。例えば、数値が5行、文字列が3行であれば、その列は数値型として読み込まれる。

対処法

まず、すべての列を文字列として読み込むようにする。もし、数値として使いたい場合は読み込んだ後に必要に応じて変換をする。

すべて文字列で読み込むにはRecordSet生成時に指定する"Extended Properties"パラメータのIMEX1を指定する。こうすることでインポートモードとなり、すべて文字列で読み込んでくれる。

※指定した列がすべて数値の場合には数値型として読み込んでしまうため注意が必要。一つでも文字列があれば文字列型として読み込んでくれる。

必ず文字列として読み込む工夫としては、Excelの1行目にすべて文字列を入力しておくことで、必ず文字列として読み込むようになる。

参考文献

ADOを使って、CSVファイルを読み込む - VBA

ADOを使い、CSVファイルにアクセスすることで、CSVファイルをDBのテーブルとして扱うことができるようになる。
ADOでの接続は以下の手順で行う

  1. プロパイダを指定する
  2. アクセスするファイルの格納フォルダの指定
  3. そのほかの設定をする
  4. 接続開始
  5. SQLの実行
  6. ヘッダーの表示
  7. 取得データの表示

サンプルコード

Sub OpenDataBase()
On Error GoTo PROC_ERR
    Dim cn          As New ADODB.Connection
    Dim Rs          As New ADODB.Recordset
    Dim sEXTENDED   As String
    Dim sSrcDir     As String   ' 接続先フォルダ
    Dim sSql        As String   ' SQL
    Dim oWs         As Worksheet
    Dim lCnt        As Long     ' ヘッダー表示のループ変数
    
    sSrcDir = "C:\Temp\ADO_TEST\"
    
    ' プロパイダの設定 
    cn.Provider = "Microsoft.ACE.OLEDB.12.0"    ' Office 2007 以降

    ' 読み込むファイルの格納フォルダのパス
    cn.Properties("Data Source") = sSrcDir
    
    ' その他のプロパティの設定
    sEXTENDED = "text"
    sEXTENDED = sEXTENDED & ";FMT=Delimited"
    sEXTENDED = sEXTENDED & ";HDR=Yes"
    cn.Properties("Extended Properties").Value = sEXTENDED
    
    ' 接続開始
    cn.Open
    
    sSql = "SELECT * FROM [CSVTEST.csv]"
    
    ' SQL実行
    Rs.Open sSql, cn
    
    If Rs.EOF Then
        ' 結果が1行もない場合終わり
        GoTo PROC_EXIT
    End If
    
    Set oWs = ThisWorkbook.Sheets("Sheet1")
    
    ' ヘッダーの表示
    For lCnt = 1 To Rs.Fields.Count
        oWs.Cells(1, lCnt).Value = "'" & Rs.Fields(lCnt - 1).Name
    Next
    
    ' 結果をそのまま表示
    oWs.Cells(2, 1).CopyFromRecordset Rs
    
    Rs.Close
    
    cn.Close
    
PROC_EXIT:
    On Error Resume Next
    
    ' 後処理
    Set Rs = Nothing
    Set cn = Nothing
    
    Exit Sub
PROC_ERR:
    MsgBox "ADO接続(CSV/TEXT)エラー:" & Err.Description & "(" & Err.Number & ")" & vbCrLf & sSrcDir, vbCritical
    GoTo PROC_EXIT
End Sub
続きを読む

1つだけ右寄せでそれ以外は左寄せ flex - CSS

flexでタイトルの通りのことをしたい

こんな感じ

f:id:tmg1998:20180423231503p:plain:w600


右寄せしたい要素にmargin-left; auto;とする!!!
左のmarginが自動になって、右寄せになる感じ!

<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child f-right"></div>
</div>
.parent {
  display: flex;
  background-color: rgba(200, 200, 200, 0.8);
}

.child {
  background-color: rgba(255, 0, 0, 0.8);
  width: 150px;
  height: 50px;
  margin: 5px;
}

.f-right {
  margin-left: auto;    /* これ!!! */
}

See the Pen 一つだけ右寄せ、それ以外は左寄せ by tamago (@tamago324) on CodePen.

参考文献

文字列の数字同士を比較する時は、数値に変換してから - JavaScript

テキストエディタ(っぽいもの)を作ってて、バグってたから調べてみた結果、

文字列の数字同士を比較と危ないということがわかった

なので、数値として扱いたいときには必ず数値に変換してから比較すること!!

github.com


文字列同士の場合、以下のように、数値同士であればtrueのものもfalseになってしまう

> "9" < "10"
< false

数値に変換すれば、思ったように動作する

> Number("9") < Number("10");
< true


失敗から学ぶことができてよかった!

参考文献

型変換 - JavaScript

JavaScriptでの型変換をメモしておく

数値 → 文字列

String()を使う

> String(1);
< "1"

>typeof String(1);
< "string"

参考文献

初心者でも迷わない!JavaScriptの数値⇔文字列変換はコレだけ覚えよ! | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト

要素の削除 - JavaScript

要素を削除するには2通りあるらしい(今のところ知っている範囲だと)

  • removeChild():親要素から子要素を削除する
  • remove():自分自身を削除する


例)child1というidをもった要素を削除したいとき

removeChild()

親要素を取得し、子要素である自分を削除する感じ

const child = document.getElementById("child1");
child.parentNode.removeChild(child);

remove()

自分自身を削除することができる

document.getElementById("child1").remove();

使い分けは?

親から見て、削除したいときにはremoveChild()がいいのかな? よくわかんない

参考文献