-
EXCELファイルの拡張子が xlsx のファイルですが、多分 EXCEL2007以降のバージョンでEXCEL2010,2013,2015などで出力される形式があります。 このファイルですが、中身はXMLファイルの集まりが圧縮されているそうなのです。 お恥ずかしい限りですが、つい最近まで知らなかったのですが、EXCELファイルをZIPファイルにリネームし圧縮を解凍すれば中身が見られます。
そこで、どうなっているのかを調べてみたので順に見ていきます。
■先ずはテスト用のEXCELファイルを作成します。簡単な内容のデータを作成します。
■フォルダの中に test.xlsx ファイルが作成されました。
■test.xlsx ファイルのコピーを作成します。
■test.xlsx のコピーファイルのファイル名を test.zip に変更します。
■test.zip ファイルを展開してやります。
以下は test.zip ファイルの上で右クリックをしたところですが、その中の「すべて展開(T)...」を選択します。 (私のPCでは各種ツールが入っていますので、変なメニューも表示されていますが)
■展開結果は以下の様になります。
展開された中のXMLファイルを見てみます。 XMLファイルの中身を見たい場合にはXML表示ソフトを使いますが、以下のフリーソフト「XMLEDITOR.NET(xml.exe)」が使いやすいと思います。 このソフトを使ってXMLファイルをのぞいてみます。
⇒XMLEDITOR .NETについて
■\test\xl\worksheets フォルダの中の sheet1.xml ファイルを「XMLEDITOR.NET(xml.exe)」で見てみます。
以上からエクセルのファイルは各種のXMLファイルで構成されていることが分かります。 尚、今回なぜエクセルの中身を解析する必要が在ったかと言いますと、PHPでのエクセル出力で、エクセルのグラフの表現がどうなっているかを調査するためでした。
VB.NETからエクセルを使う場合はエクセルのオブジェクトからそのメソッド等を利用して操作ができるので、中身までは意識しませんが、 PHPからの処理ではPHPExcleライブラリだけでは難しい部分もありますので、参考になればと思います。関連する記事
⇒Excel ファイルの操作について(Microsoft.Office.Interop.Excel COM参照)
PR -
以前の記事でCSVファイルに書込む処理を紹介しましたが、 今回はその関数を利用して DataGridViw コントロールからCSVファイルへのデータ書込みを行います。
⇒CSVファイルの書込について :[System.IO.StreamWriter]
DataGridViw から WriteCsv:CSVファイル書込処理 に指示する文字列配列を作成し、ファイル書込みを行います。 DataGridViw の列ヘッダーからCSVの先頭行のヘッダーデータを取得します。 更に DataGridViw の各行データから、その行のセルデータから文字列配列を作成します。
最初フォームに DataGridView コントロールを配置すると AllowUserToAddRows プロパティが True なので、 DataGridView の最後の行に新規行(*行)が表示される様になります。 (この設定のままで、どんどん新規のデータを入力できます。)
この新規行は何も入力がされていない状態ですので、 CSVファイルにはデータとして登録しない様に DataGridView の行の IsNewRow プロパティが True の場合には 処理しない様にしています。
尚、以下の例ではフォームロードイベント処理で DataGridView の列数を5個として生成を行っています。DataGridView からCSVファイルへの書込
Public Class frmDGV2CSV ' フォームロード時処理 Private Sub frmDGV2CSV_Load(sender As Object, e As EventArgs) Handles Me.Load Try 'DataGridView列数を5に固定 Dim arrColName() As String = {"COL1", "COL2", "COL3", "COL4", "COL5"} For Each strName As String In arrColName Me.dgv.Columns.Add(strName, strName) Next Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub ' [WriteCSV From DataGridView]ボタンクリック処理 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Try 'DataGridViewからCSVファイルへの書込処理の呼出 If WriteCsvFromDGV(Me.dgv, "testw.csv") = True Then MsgBox("CSVファイル書込・正常") Else MsgBox("CSVファイル書込・エラー") End If Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub ''' ----------------------------------------------------------------------------- ''' <summary> ''' DataGridViewからCSVファイルへの書込処理 ''' (WriteCsv:CSVファイルの書込処理の利用による) ''' </summary> ''' <param name="dgv">DataGridView</param> ''' <param name="astrFileName">ファイル名</param> ''' ----------------------------------------------------------------------------- Private Function WriteCsvFromDGV(ByVal dgv As DataGridView, ByVal astrFileName As String) As Boolean WriteCsvFromDGV = False Try 'DataGridView全体のデータ領域 Dim arrData()() As String = Nothing '1行分を読込 Dim arrHead As String() = Nothing '列ヘッダの名称取得 For col As Integer = 0 To Me.dgv.Columns.Count - 1 '1列分の領域拡張 ReDim Preserve arrHead(col) '列のヘッダデータ退避 arrHead(col) = CStr(Me.dgv.Columns(col).HeaderCell.Value) Next '1行分の領域拡張 ReDim Preserve arrData(0) '列ヘッダ名退避 arrData(0) = arrHead 'データ行数分の処理 For row As Integer = 0 To Me.dgv.Rows.Count - 1 '新規行は処理しない If Me.dgv.Rows(row).IsNewRow Then Continue For End If '1行分を読込 Dim arrLine As String() = Nothing '列数分の処理 For col As Integer = 0 To Me.dgv.Columns.Count - 1 '1列分の領域拡張 ReDim Preserve arrLine(col) '列データ退避 arrLine(col) = CStr(Me.dgv.Rows(row).Cells(col).Value) Next '1行分の領域拡張 ReDim Preserve arrData(row + 1) '1行データ退避 arrData(row + 1) = arrLine Next '実際のCSVファイルの書込み Return WriteCsv(astrFileName, arrData) Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Function ''' ----------------------------------------------------------------------------- ''' <summary> ''' CSVファイルの書込処理 ''' </summary> ''' <param name="astrFileName">ファイル名</param> ''' <param name="aarrData">書込データ文字列の2次元配列</param> ''' <returns>True:結果OK, False:NG</returns> ''' <remarks>カラム名をファイルに出力したい場合は、書込データの先頭に設定すること</remarks> ''' ----------------------------------------------------------------------------- Private Function WriteCsv(ByVal astrFileName As String, ByVal aarrData As String()()) As Boolean WriteCsv = False 'ファイルStreamWriter Dim sw As System.IO.StreamWriter = Nothing Try 'CSVファイルに書込に使うEncoding Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS") '書き込むファイルを開く sw = New System.IO.StreamWriter(astrFileName, False, enc) For Each arrLine() As String In aarrData Dim blnFirst As Boolean = True Dim strLIne As String = "" For Each str As String In arrLine If blnFirst = False Then '「,」(カンマ)の書込 sw.Write(",") End If blnFirst = False '1カラムデータの書込 str = """" & str & """" sw.Write(str) Next '改行の書込 sw.Write(vbCrLf) Next '正常終了 Return True Catch ex As Exception 'エラー MsgBox(ex.Message) Finally '閉じる If sw IsNot Nothing Then sw.Close() End If End Try End Function End Class
DataGridView にデータを入力したところのフォームの表示は以下の様になります。
[WriteCSV From DataGridView] ボタンを押下すると以下の様なCSVファイルが書き込まれます。
CSVファイルの内容
"COL1","COL2","COL3","COL4","COL5" "111","22222","33333","4444","55555" "aaa","bbb","cccccc","ddd","ee" "AAA","22","CCCCC","DDDD","EEE"
関連する記事
⇒CSVファイルの読込について :[Microsoft.VisualBasic.FileIO.TextFieldParser]
⇒CSVファイルの書込について :[System.IO.StreamWriter]
⇒CSVファイルの DataGridView への読込について
-
以前の記事でCSVファイルを読込む処理を紹介しましたが、 今回はその関数を利用して DataGridViw コントロールへのデータ設定を行います。
⇒CSVファイルの読込について :[Microsoft.VisualBasic.FileIO.TextFieldParser]
DataGridViw への設定では ReadCsv:CSVファイル読込処理 から返された文字列配列を基に、各カラムに文字列として設定を行います。 DataGridViw は列が無いと対象セルへの設定ができないので、 ReadCsv 処理後最初に先頭行の列数を設定します。また、各行の設定の前で列数の変化があれば拡張を行っています。CSVファイルの DataGridView への読込
Imports Microsoft.VisualBasic.FileIO Public Class frmCSV2DGV ''' ----------------------------------------------------------------------------- ''' <summary> ''' CSVファイルの読込処理 ''' </summary> ''' <param name="astrFileName">ファイル名</param> ''' <param name="ablnTab">区切りの指定(True:タブ区切り, False:カンマ区切り)</param> ''' <param name="ablnQuote">引用符フラグ(True:引用符で囲まれている, False:囲まれていない)</param> ''' <returns>読込結果の文字列の2次元配列</returns> ''' ----------------------------------------------------------------------------- Private Function ReadCsv(ByVal astrFileName As String, ByVal ablnTab As Boolean, ByVal ablnQuote As Boolean) As String()() ReadCsv = Nothing 'ファイルStreamReader Dim parser As Microsoft.VisualBasic.FileIO.TextFieldParser = Nothing Try 'Shift-JISエンコードで変換できない場合は「?」文字の設定 Dim encFallBack As System.Text.DecoderReplacementFallback = _ New System.Text.DecoderReplacementFallback("?") Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("shift_jis", _ System.Text.EncoderFallback.ReplacementFallback, encFallBack) 'TextFieldParserクラス parser = New Microsoft.VisualBasic.FileIO.TextFieldParser(astrFileName, enc) '区切りの指定 parser.TextFieldType = FieldType.Delimited If ablnTab = False Then 'カンマ区切り parser.SetDelimiters(",") Else 'タブ区切り parser.SetDelimiters(vbTab) End If If ablnQuote = True Then 'フィールドが引用符で囲まれているか parser.HasFieldsEnclosedInQuotes = True End If 'フィールドの空白トリム設定 parser.TrimWhiteSpace = False Dim strArr()() As String = Nothing Dim nLine As Integer = 0 'ファイルの終端までループ While Not parser.EndOfData 'フィールドを読込 Dim strDataArr As String() = parser.ReadFields() '戻り値領域の拡張 ReDim Preserve strArr(nLine) '退避 strArr(nLine) = strDataArr nLine += 1 End While '正常終了 Return strArr Catch ex As Exception 'エラー MsgBox(ex.Message) Finally '閉じる If parser IsNot Nothing Then parser.Close() End If End Try End Function ''' ----------------------------------------------------------------------------- ''' <summary> ''' CSVファイルのDataGridViewへの読込処理 ''' (ReadCsv:CSVファイルの読込処理の利用による) ''' </summary> ''' <param name="dgv">DataGridView</param> ''' <param name="astrFileName">ファイル名</param> ''' <param name="ablnTab">区切りの指定(True:タブ区切り, False:カンマ区切り)</param> ''' <param name="ablnQuote">引用符フラグ(True:引用符で囲まれている, False:囲まれていない)</param> ''' ----------------------------------------------------------------------------- Private Sub ReadCsvToDGV(ByVal dgv As DataGridView, ByVal astrFileName As String, Optional ByVal ablnTab As Boolean = False, Optional ByVal ablnQuote As Boolean = False) Try 'CSVファイル読込処理 Dim arrCsv()() As String = ReadCsv(astrFileName, ablnTab, ablnQuote) 'DataGridView クリア dgv.Rows.Clear() '列数の設定 dgv.ColumnCount = arrCsv(0).Length Dim row As Integer = 0 For Each arr In arrCsv 'DataGridView 新規行を追加 dgv.Rows.Add() 'DataGridViewの列数がデータ配列数より小さい場合は列拡張 If dgv.ColumnCount < arr.Length Then dgv.ColumnCount = arr.Length End If For col As Integer = 0 To arr.Length - 1 'セルに列、行を指定して値の設定 dgv(col, row).Value = arr(col) Next '次の行へ row += 1 Next Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'CSVファイルをDataGridViewへ読込処理 ReadCsvToDGV(Me.DataGridView1, "test2.csv") End Sub End Class
以下の様なCSVファイルを読込みます。CSVファイルの内容
TEST1,TEST2,TEST3 1000,2000,3000 aaaa,bbbb,cccc,dddd 000,111,4444,55555,6666 AAAAAAA,BBBBB
読込んだフォームの表示は以下の様になります。
この場合 DataGridViw の列ヘッダに設定はしていませんので、CSVファイルの先頭行にヘッダが存在する場合を考慮した 読込関数を以下に記します。DataGridViw への設定関数と実行例の部分のみを抜粋しています。CSVファイルの DataGridView への読込2
''' ----------------------------------------------------------------------------- ''' <summary> ''' CSVファイルのDataGridViewへの読込処理 ''' (ReadCsv:CSVファイルの読込処理の利用による) ''' </summary> ''' <param name="dgv">DataGridView</param> ''' <param name="astrFileName">ファイル名</param> ''' <param name="ablnTab">区切りの指定(True:タブ区切り, False:カンマ区切り)</param> ''' <param name="ablnQuote">引用符フラグ(True:引用符で囲まれている, False:囲まれていない)</param> ''' <param name="ablnHeader">先頭行が列ヘッダ</param> ''' <param name="ablnExtendColumn">列数の拡張を行う指示</param> ''' ----------------------------------------------------------------------------- Private Sub ReadCsvToDGV(ByVal dgv As DataGridView, ByVal astrFileName As String, Optional ByVal ablnTab As Boolean = False, Optional ByVal ablnQuote As Boolean = False, Optional ByVal ablnHeader As Boolean = False, Optional ByVal ablnExtendColumn As Boolean = True) Try 'CSVファイル読込処理 Dim arrCsv()() As String = ReadCsv(astrFileName, ablnTab, ablnQuote) 'DataGridView クリア dgv.Rows.Clear() Dim row As Integer = 0 Dim blnFirst As Boolean = True For Each arr In arrCsv If blnFirst = True Then blnFirst = False If ablnHeader = True Then '先頭行が列ヘッダの場合 dgv.Columns.Clear() For Each strColName In arr dgv.Columns.Add(strColName, strColName) Next Continue For Else '列数の設定 dgv.ColumnCount = arrCsv(0).Length End If End If 'DataGridView 新規行を追加 dgv.Rows.Add() 'DataGridViewの列数がデータ配列数より小さい場合は列拡張 If ablnExtendColumn = True And dgv.ColumnCount < arr.Length Then dgv.ColumnCount = arr.Length End If For col As Integer = 0 To arr.Length - 1 If col >= dgv.Columns.Count Then Exit For End If 'セルに列、行を指定して値の設定 dgv(col, row).Value = arr(col) Next '次の行へ row += 1 Next Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'CSVファイルをDataGridViewへ読込処理:先頭行が列ヘッダで列数拡張 ReadCsvToDGV(Me.DataGridView1, "test2.csv", False, False, True, True) MsgBox("OK") 'CSVファイルをDataGridViewへ読込処理:先頭行が列ヘッダで列数拡張無し ReadCsvToDGV(Me.DataGridView1, "test2.csv", False, False, True, False) End Sub
実行結果(先頭行が列ヘッダで列数拡張)は以下の様になります。
メッセージ表示後(先頭行が列ヘッダで列数拡張無し)の表示は以下の様になります。
関連する記事
⇒CSVファイルの読込について :[Microsoft.VisualBasic.FileIO.TextFieldParser]
⇒CSVファイルの書込について :[System.IO.StreamWriter]
⇒DataGridView からCSVファイルへの書込について
-
小学校でのプログラミング教育は必要かと考えると、私は、必要無いと思います。 なぜ小学校でプログラミング教育を行うのかとの問いには、一般的に、 「これからのAI時代に対応するためには少なからずコンピュータの知識が必要になってくるので、小学校から教えておいた方が良い」 とする風潮が在る様に思います。
しかし、本当にそうでしょうか。 実際に小学生が出来ることには限界があるもので、授業で行われるプログラミング教育は、 ロボットの様なものをそれ様に作られたプログラミング言語(言語と呼ぶにはどうかと思いますが)で 動きの制御を行ったりするらしいです。
私が思うに「進め」「とまれ」「右に行け」「左に行け」「これを何回か行え」などの命令を並べて処理をさせると思います。 しかし、この様なことではたしてプログラミングの基礎が学べるのでしょうか。
プログラミングの基礎と言えば、アルゴリズム(算法と訳されます)を習うことから始まったりします。 アルゴリズムと言えば、やはり数学的(もしくは算数的)な思考が元となって成り立っています。 そのために論理的な思考を養える算数が基本ではないでしょうか。 実際にプログラマーをしている立場からすれば、おさえておくべき教科としては 「国語(日本語)」「数学(算数)」「英語」「理科」ではないでしょうか。 日本人として会話の基本は日本語ですから、日本語がしっかりしていないと全ての教科を勉強することはできません。 (この拙い文章を書いている私が言うのもおかしいですが)
後は「英語」は今後のグローバル化を見据えて必要になるでしょう。 プログラミングの為のウエブページを見ても圧倒的に英語のページの方が情報が多いものです。 英語は必要だと思います。
何かをプログラムで処理するなり、動作させるなりする場合には、 対象となるものを論理的に捉えてそれらを道筋を立てて考えなければなりません。 小学校のどの学年からプログラミングを教えていくのかは分かりませんが、 算数などの計算がしっかりできたうえで行った方が良いと思います。
(私は基本的には、小学生の知識レベルではプログラミングは無理があると考えます。)
それでも、小学校でプログラミング教育は始まってしまうので、心配な親御さんはいらっしゃるのではないでしょうか。 最近読んだ本ですが、以下の本にその参考となることが載っています。 この本の中でも書かれていますが、実際のプログラミングをそればかり行うのではなく、 先ずは子供の「考える力」「興味を持つ力」などを育てることが必要と書かれています。 やはり、プログラミングの技巧的な部分ばかりでは無く、プログラミングに必要な素養を育てるようです。 私も何となく納得しました。
⇒知識ゼロのパパ・ママでも大丈夫! 「プログラミングができる子」の育て方
プログラミング教育ですが、平成の時代に行われた「ゆとり教育」の二の舞にならなければと思うのですが。
結局は「ゆとり教育」からの揺り戻しが在って、現在は少し詰め込みを戻したようですが、あの「ゆとり教育」の失敗はちゃんと検証されたのでしょうか? 甚だ疑問です。
「ゆとり教育」も今となっては「総合」の時間などは社会に出た時に必要となる要素を勉強できて良かったのではと思います。 しかし、当時「総合」を教える教師側にも問題があって何をどの様に教えたらいいか分かっていなかったと思います。 折角目指していたことはよかったのですから。
今回の「プログラミング教育」ですが、「ゆとり教育」の時と同じ様にならないかが心配です。 これを教える先生方の教育も必要ですし、年齢の上の先生には正直きついのではないでしょうか。 まあ、これには「プログラミング教育」の民間の力が必要かもしれません。 プログラマのプロから教わることは多いと思います。
-
プログラムの多重起動を抑止する方法(自分自身が1回しか起動されないようにする方法)について説明します。 抑止する方法はいろいろあるのですが Mutex を使った方法が比較的簡単だと思いますので、今回はその方法について記します。
先ずは Mutex についてですが、これは排他制御を行う為の仕組みで、現在それを「使用中」か「未使用」かを示すフラグの様なものです。 あるプロセス(実行プログラム)が、ある Mutex を取得しそのフラグを「使用中」にします。 再度そのプロセスを実行した場合にその Mutex は既にフラグが「使用中」であれば、起動を中止する様にします。 (簡単な「セマフォ」であるとも言えます)
.NET には Mutex クラスがありますのでそれを使うことになります。Mutex クラスについて
<コンストラクタ> System.Threading.Mutex(initiallyOwned As Boolean, name As String, ByRef createdNew As Boolean) ・initiallyOwned:名前付きシステム ミューテックスの初期所有権を付与する場合は true。 それ以外の場合は false。 ・name :Mutex の名前です。 ・createdNew :指定した名前付きシステム ミューテックスが作成された場合はブール値 true が格納されます。 指定した名前付きシステム ミューテックスが既に存在する場合は false が格納されます。
Mutexを使ったプログラムは以下の様になります。 上記の Mutex クラスを生成した結果 createdNew フラグを確認することで Mutex が生成されたかが分かります。 true でなければ実際の処理は行わない様にして処理を抜ける様にします。
Mutexを使ったプログラムの多重起動の抑止
Module MdlMain 'Main関数 Sub Main() 'ミューテックス名(一意な名前にすること) Dim mstrMutexName As String = "TestProgramName" '(仮の名前) 'ミューテックス Dim mMutex As System.Threading.Mutex = Nothing '新規作成フラグ Dim blnCreated As Boolean = False Try Try '名前付きシステム ミューテックスの初期所有権を付与 mMutex = New System.Threading.Mutex(True, mstrMutexName, blnCreated) Catch ex As Exception MessageBox.Show("多重起動はできません。Mutex Error[" & ex.Message & "]") Return End Try 'ミューテックスが作成されたか調べる If blnCreated = False Then MessageBox.Show("多重起動はできません。") Return End If '既設のMainメソッドの処理を実行(表示させたいフォームを表示) Dim frm As New frmTest Application.Run(frm) Finally If blnCreated Then 'ミューテックスを解放する mMutex.ReleaseMutex() End If mMutex.Close() End Try End Sub End Module
プログラム中の frmTest は通常のフォームを作成しただけで、フォームの動きは特にプログラミングしていません。
実行の様子を下図に示します。作成された実行ファイルを起動し、その後同じものを起動した時の様子です。
尚、今回の例では Sub Main() メソッドを開始指定(エントリポイント指定)をしてやるのですが、 「プロジェクト・プロパティ」の中の「アプリケーション」タブにある「スタートアップフォーム」でエントリポイントを指定するのですが、 このままでは Sub Main() が中に表示されません。
そこで「アプリケーションフレームワークを有効にする」チェックボックスを無効にすると 「スタートアップフォーム」は「スタートアップオブジェクト」の表示となり、 Sub Main() が出てきますので、それを指定します。