ゲームエフェクトデザイナーのブログ | A Real-Time VFX Artist's Blog

About Making Materials on UE, Making Tools with C#, etc

C#でサブフォルダの総サイズのリストアップ(DataGridView編)

前回は同じ内容のツールでListBoxにリストアップする形でしたが、今回はDataGridViewにリストアップする方法を備忘録としてメモしておきます。

外観はこんな感じ。

f:id:moko_03_25:20170812222614j:plain

DataGridViewの扱いに慣れれば、後はCSV読み込みと書き出し、余力があればExelのデータを扱えるライブラリを導入して直接xlsxファイルで書き出すことができるようになれば、業務でのお役立ち度も一気に増して幸せになれそうな気がします。

さて、あるフォルダパス直下のサブフォルダ1つ1つのファイルサイズをリストアップするまでの記述は前回の記事とほとんど変わらないので、ここでは前回と違う部分だけピックアップしたいと思います。

サブフォルダ1つ1つの総ファイルサイズを配列で取得するメソッド


DataGridViewのやり取りの部分がまだよく分かっていないので、恐らくもっと楽な方法があると思うのですが、自分なりに調べて試してみたのは‥1つのサブフォルダに対して「フォルダ名」と「ファイルサイズ」の2つの要素を二次元配列に格納して、DataGridViewの一列目と二列目にそれぞれの要素を追加していく方法です。

//サブフォルダ1つ1つの総ファイルサイズを配列で取得
public string[,] GetSubFolderSize(string subFolders)
{
  //サブフォルダの数分の配列"size"と"sizeSt"を定義
  int el = subFolders.Length; //サブフォルダの要素数(element)
  long size = new long[el]; //整数の配列

  string[,] sizeSt = new string[el, 2]; //文字列の2次元配列
  string fn; //フォルダネームを一時的に保存する変数

  //配列の要素の数だけ処理
  for (int i = 0; i < el; i++)
  {
    //入力したパスのフォルダ名を取得
    fn = Path.GetFileName(subFolders[i]);

    //入力したパスをDIrectoryInfoクラスのオブジェクトに代入
    DirectoryInfo chkPath = new DirectoryInfo(subFolders[i]);
    //総ファイルサイズをMiB単位で配列"size"に代入
    size[i] = GetDirectorySize(chkPath) / 1024 / 1024;
    //文字列に変換して配列"sizeSt"に代入
    sizeSt[i, 0] = fn;
    sizeSt[i, 1] = size[i].ToString("D");
  }

  return sizeSt;
}


戻り値
と変数”sizeSt”をString型の二次元配列にして、フォルダ名ファイルサイズを別々に格納しています。

本当はフォルダ名はString型サイズはLong型で返したいところですが、とりあえず今回は勉強を兼ねて二次元配列でやってみた感じになります。

Enterでパスを取得してDataGridViewにリストアップ


Enterキーを入力した際の挙動の部分だけ抜粋しています。

列のヘッダーの表示名を設定して、ファイルサイズの列は右寄せに設定。
最後に各列に二次元配列の中身を追加していっています。

//サブフォルダのパスを全て取得
string[] subFolders = GetSubFolderPath(path);
//サブフォルダの要素数
int el = subFolders.Length;

//サブフォルダの数分の2次元配列"sizeSt"を定義
string[,] sizeSt = new string[el, 2];

//全てのサブフォルダごとの合計サイズを取得
sizeSt = GetSubFolderSize(subFolders);

//DataGridViewの項目名を指定
dataGridViewResult.Columns.Add("", "フォルダ名");
dataGridViewResult.Columns.Add("", "総サイズ(MB)");
//行ヘッダを非表示にする ※Formデザイナーのプロパティ内でも設定可能
dataGridViewResult.RowHeadersVisible = false;
//2列目を右寄せ表示にする
dataGridViewResult.Columns[1].DefaultCellStyle.Alignment =
  DataGridViewContentAlignment.MiddleRight;

//二次元配列を1列目と2列目に追加していく
for (int i = 0; i < el; i++)
{
  //行を追加
  dataGridViewResult.Rows.Add();
  //行の1列目にフォルダ名を入力
  dataGridViewResult.Rows[i].Cells[0].Value = sizeSt[i, 0];
  //行の2列目にサイズをLongに型変換して入力(ソート問題回避のため)
  dataGridViewResult.Rows[i].Cells[1].Value = long.Parse(sizeSt[i, 1]);
}


二次元配列は初めて試しましたが、一応うまくいっているようでホっ。
ファイルサイズをString型からLong型に変換している理由は後述しています。

下記の様々な記事を参考にさせて頂きました。

【C#】2次元配列の宣言・初期化・代入

【C# DataGridView】一次元配列を設定する | ITLAB51.COM

DataGridの一番下の新しい行(*行)が表示されないようにする: .NET Tips: C#, VB.NET

DataGridViewでの行の追加と削除 - 理想のユーザ・インターフェイスを求めて

文字列を数値に変換する、数値を文字列に変換する: .NET Tips: C#, VB.NET

DataGridViewの内容のクリップボードへのコピーとクリア


最後におまけです。
DataGridViewの内容を全てクリップボードへコピーする方法と、全て消去する方法です。

//「クリップボードへコピーする」ボタンの挙動
private void buttonCopy_Click(object sender, EventArgs e)
{
  //全ての列の全ての行を選択
  for (int i = 0; i < dataGridViewResult.ColumnCount; i++)
  {
    for (int j = 0; j < dataGridViewResult.RowCount; j++)
    {
      dataGridViewResult[i, j].Selected = true;
    }
  }
  //選択内容をクリップボードへコピーする
  //ヘッダを含めて同じ行のセル間はTab区切りにする
  dataGridViewResult.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
  Clipboard.SetDataObject(dataGridViewResult.GetClipboardContent());
}

//「クリア」ボタンでDataGridViewの内容を消去
private void buttonClear_Click(object sender, EventArgs e)
{
  //全ての行の内容をクリア
  dataGridViewResult.Rows.Clear();
  //全ての列の内容をクリア
  dataGridViewResult.Columns.Clear();
} 


こちらも下記の様々な記事からにお世話になりました。

【C# DataGridView】内容をクリップボードにコピーする | ITLAB51.COM

DataGridViewで選択されたセルをクリップボードにコピーできるようにする: .NET Tips: C#, VB.NET

【C#】DataGridViewをプログラムで初期化、列編集する方法 – Output48

他には、Formデザイナーのプロパティの方に以下のような設定があります。

・AllowUser~~ 行や列のサイズ変更や追加/削除等を許可するか
・ClipboardCopyMode クリップボードにコピーする際の設定
・ColumnHeadersHeightSizeMode 列ヘッダーの高さの調整
・ReadOnly ユーザーのセルの編集を許可するか(Trueで編集不可)
・AutoSizeColumnsMode 可視列の自動サイズ調整の設定
・RowHeadersVisible 行ヘッダーを表示するかどうか


それから、DataGridView上で数値を文字列で扱っていると、ヘッダーをクリックして昇順/降順にソートすると正しく数字の大きさ順でソートしてくれません。
なのでファイルサイズはLong型に変換してからDataGridViewに入力した訳です。

下記の記事のような方法もあるようですが。。

DataGridViewの行の並び替えの方法を変更する: .NET Tips: C#, VB.NET

ADO.NET入門記-031 (DataTableにて文字列値の列を数値ソートする) - いろいろ備忘録日記

プロジェクトデータと実行ファイル


Googleドライブにアップしました。ライセンスはMITです。

MyTool_FolderSizeCheck_DataGridView.zip - Google ドライブ

binフォルダの中にexeが入っています。