1.高速化の定石
Form_Loadなどで。
DataGridViewの画面ちらつきをおさえ高速表示するために、DoubleBufferedを有効にする。
// DataGirdViewのTypeを取得
System.Type dgvtype = typeof(DataGridView);
// プロパティ設定の取得
System.Reflection.PropertyInfo dgvPropertyInfo = dgvtype.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
// 対象のDataGridViewにtrueをセットする
dgvPropertyInfo.SetValue(dataGridView1, true, null);
2.データテーブルのセット~書式設定
//件数確保
int 件数 = dt.Rows.Count;
label読込行数.Text = 件数.ToString() + " 行";
//dataGridViewにデータテーブルをセットする。
dataGridView1.DataSource = dt;
//dataGridViewの設定
//ユーザの操作規制 ←これはFormのLoadへ持って行っても良い
dataGridView1.ReadOnly = true; //読取専用
dataGridView1.AllowUserToDeleteRows = false; //行削除禁止
dataGridView1.AllowUserToAddRows = false; //行挿入禁止
dataGridView1.AllowUserToResizeRows = false; //行の高さ変更禁止
dataGridView1.RowHeadersVisible = false; //行ヘッダーを非表示にする
dataGridView1.MultiSelect = false; //セル、行、列が複数選択禁止
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; //セルを選択すると行全体が選択されるようにする
//並び替えができないようにする 【注意】データがセットされた後でしか効かないよ。
foreach (DataGridViewColumn c in dataGridView1.Columns)
c.SortMode = DataGridViewColumnSortMode.NotSortable;
//コピーモード
dataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
//基本フォントの設定
dataGridView1.DefaultCellStyle.Font = new System.Drawing.Font("MS UI Gothic", 10);
//ヘッダーの色等
dataGridView1.EnableHeadersVisualStyles = false; // Visualスタイルを使用しない
dataGridView1.ColumnHeadersDefaultCellStyle.BackColor = Color.LightGray;
dataGridView1.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("MS UI Gothic", 9);
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
//ヘッダ高さ
dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;
dataGridView1.ColumnHeadersHeight = 30;
//ヘッダー名称変更
dataGridView1.Columns["住所1"].HeaderCell.Value = "県名";
//カラム幅設定
dataGridView1.Columns[0].Width = 50; //社員番号
dataGridView1.Columns[1].Width = 100; //カラム名
dataGridView1.Columns[2].Width = 70; //カラム名
dataGridView1.Columns[3].Width = 70; //カラム名
dataGridView1.Columns[4].Width = 70; //カラム名
dataGridView1.Columns[5].Width = 80; //カラム名
//寄せ
dataGridView1.Columns["社員番号"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
//数値を3けた区切
dataGridView1.Columns["金額"].DefaultCellStyle.Format = "#,0";
//小数第2位まで表示するだけ
dataGridView1.Columns["増加率"].DefaultCellStyle.Format = "N2";
//小数第2位まで表示して、”%”を加える。
dataGridView1.Columns["増加率"].DefaultCellStyle.Format = @"#,##0.00%";
//列指定の太字
dataGridView1.Columns["社員番号"].DefaultCellStyle.Font = new Font(dataGridView1.Font, FontStyle.Bold);
//値取得2種(値2の方が可読性が良いかな?)
string 値1 = dataGridView1[2, 4].Value.ToString(); //【注意】[col,row] の順。 行列は0始まり。
string 値2 = dataGridView1.Rows[0].Cells["社員番号"].Value.ToString();
3..DataSource から DataTble へ値を渡す。
//参照渡し
DataTable dt1 = new DataTable();
dt1 = (DataTable)dataGridView1.DataSource;
//値渡し
DataTable dt2 = new DataTable();
dt2 = ((DataTable)dataGridView1.DataSource).Copy() ;
4.セルの値によって行の色を変更する。
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//セルの値によって行のバックカラーを変更する。
DataGridView dgv = (DataGridView)sender;
//セルの列を確認
if (dgv.Columns[e.ColumnIndex].Name == "許可" && e.Value.ToString() == "不可")
{
//単一セルのみ
e.CellStyle.BackColor = Color.Violet;
//対象行
dgv.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.LightGray;
}
if (dgv.Columns[e.ColumnIndex].Name == "許可" && e.Value.ToString() == "")
{
//そうでない場合は戻す
//単一セルのみ
e.CellStyle.BackColor = Color.White;
//対象行
dgv.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.White;
}
}
5.チェックボックス型セルの値確定タイミング
dataGridViewのチェックボックス型セルをクリックして、trueになった瞬間(チェックマークが表示された瞬間)に他の動作を起こしたかったが、どうしても実装できなかった。
ネットで教えてもらったのは…
「チェックマークが表示されていも内部の値は変らない、次のセルを選択した際にそれが確定される。チェックマークが表示/非表示された瞬間に値(true/false)を確定させるには、DataGridView.CommitEdit を呼ぶ必要がある」ということだった。
あのチェックマークは見えてるだけなんや~
そんなん判らんでぇ…(TT)…サンプルは以下の通り。
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
// 0番目がチェックボックス型の列として、これだけを処理対象とする
if (dataGridView1.CurrentCell.ColumnIndex != 0) return;
// 値を確定する!!!
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
//ここに、すぐさま起こしたいコードを書く
}
6.選択したセルの行のボトムに赤罫線を描く
int widthAllCol = 0; //各カラム幅の合計値
//private int prevSelectRow = -1;
private void Form1_Load(object sender, EventArgs e)
{
// DataTableの個所は「猫の気ままなC#日記」さんのコードを利用させてもらってます。
// ありがとうございます。
DataTable dt = new DataTable("Table1");
string[] id = { "S0001", "S0002", "S0003", "S0004", "S0005", "S0006" };
string[] name = { "あんぱん", "メロンパン", "カレーパン", "いちごじゃむパン", "チョココロネ", "クロワッサン" };
string[] value = { "100", "105", "110", "115", "120", "125" };
// DataTableに列を追加します。
dt.Columns.Add("商品番号");
dt.Columns.Add("商品名");
dt.Columns.Add("価格");
// DataTableにデータを格納します。
for (int i = 0; i < 5; i++)
{
dt.Rows.Add(dt.NewRow());
dt.Rows[i]["商品番号"] = id[i];
dt.Rows[i]["商品名"] = name[i];
dt.Rows[i]["価格"] = value[i];
}
//dataGridView1に表示
dataGridView1.DataSource = dt;
//dataGridView1の基本設定
dataGridView1.ReadOnly = true; //読取専用
dataGridView1.AllowUserToDeleteRows = false; //行削除禁止
dataGridView1.AllowUserToAddRows = false; //行挿入禁止
dataGridView1.AllowUserToResizeRows = false; //行の高さ変更禁止
dataGridView1.RowHeadersVisible = false; //行ヘッダーを非表示にする
dataGridView1.MultiSelect = true; //セル、行、列が複数選択禁止
//dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; //セルを選択すると行全体が選択されるようにする
//ここで全カラム幅を計算する!
widthAllCol = 0;
for (int i = 0; i < dataGridView1.ColumnCount; i++)
{
widthAllCol += dataGridView1.Columns[i].Width; //各カラム幅の合計値
}
}
private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
Pen penRed = new Pen(Color.Red, 2);
Pen penOriginal = new Pen(SystemColors.ControlDark, 1); //デフォルトの罫線の色
if (e.RowIndex == dgv.CurrentRow.Index)
{
//オリジナルコード
//参考にさせて頂いた先
//http://ssk-development.blogspot.com/2017/09/datagridview_5.html
//https://tt195361.hatenablog.com/entry/2015/05/22/164840
//int startX = dgv.RowHeadersVisible ? dgv.RowHeadersWidth : 0;
//int startY = e.RowBounds.Top + 1;
//int endX = startX + dgv.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) - dgv.HorizontalScrollingOffset;
int startX = 0;
int startY = e.RowBounds.Top + e.RowBounds.Height - 1;
int endX = widthAllCol;
e.Graphics.DrawLine(penRed,
startX,
startY,
endX,
startY);
}
else
{
int startX = 0;
int startY = e.RowBounds.Top + e.RowBounds.Height - 1;
int endX = widthAllCol;
e.Graphics.DrawLine(penOriginal,
startX,
startY,
endX,
startY);
}
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
DataGridView dgv = (DataGridView)sender;
widthAllCol = 0;
for (int i = 0; i < dgv.ColumnCount; i++)
{
widthAllCol += dgv.Columns[i].Width; //各カラム幅の合計値
}
//全面か1行づつは、処理速度見ながら判断のこと
//書き直し(全面)
dataGridView1.Invalidate();
//書き直し(1行づつ)
//if (prevSelectRow != -1) dataGridView1.InvalidateRow(prevSelectRow);
//if (dataGridView1.SelectedCells.Count != 0)
//{
// prevSelectRow = dataGridView1.SelectedCells[0].RowIndex;
// dataGridView1.InvalidateRow(prevSelectRow);
//}
}
7.エクセルファイルをプロジェクトに参加させ、グリッドに表示する
①エクセルファイルをプロジェクトに参加させる方法
判ってしまえば、そうかとなるのですが・・・
こちらの方々のページを参考にさせて頂きました。↓
http://kanesuzu-san.com/visualstudio-file-tsuika
https://raishin.xyz/post-201/
②エクセルファイルをdataGridView1.DataSourceに設定する方法
対象ファイル:エクセル2013の.xlsxファイル
【注意】エクセルのバージョンによって、設定値が異なります。
参考にさせて頂いたページ↓
https://qiita.com/unarist/items/6cc35bb9fe502ced332f
System.Data.OleDb.OleDbConnection MyConnection;
System.Data.DataSet DtSet;
System.Data.OleDb.OleDbDataAdapter MyCommand;
MyConnection = new System.Data.OleDb.OleDbConnection(@"provider=Microsoft.ACE.OLEDB.15.0;Data Source='..\..\元データ.xlsx';Extended Properties=Excel 8.0;");
MyCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [Sheet1$]", MyConnection);
MyCommand.TableMappings.Add("Table", "TestTable");
DtSet = new System.Data.DataSet();
MyCommand.Fill(DtSet);
dataGridView1.DataSource = DtSet.Tables[0];
MyConnection.Close();
8.データベース問合せ結果を一発でグリッドに表示する。
using (SqlConnection connection = new SqlConnection(DB接続文字列)
using (var command = connection.CreateCommand())
{
try
{
// データベースの接続開始
connection.Open();
string SQL ="select ...";
// SQLの設定
command.CommandText = SQL;
// SQLの実行
var adapter = new SqlDataAdapter(command);
adapter.Fill(dt);
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
throw;
}
finally
{
// データベースの接続終了
connection.Close();
}
}
dataGridView1.DataSource = dt;
9.グリッドにドラッグしたファイルを読み込む
[準備] フォーム上にDataGridViewとTextBoxを配置する。
private void dataGridView1_DragDrop(object sender, DragEventArgs e)
{
//【リセット!】↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//表示系のリセットが必要ならここで実施
//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop, false);
for (int i = 0; i < files.Length; i++)
{
string fileName = files[i];
textBoxドロップパス.Text = fileName;
}
}
private void dataGridView1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.All;
}
else
{
e.Effect = DragDropEffects.None;
}
}
[Sheet1]シートのデータを読み込む
private void textBoxドロップパス_TextChanged(object sender, EventArgs e)
{
int errorRow = 0;
string error = "無"; //有無
//[準備1]Textが空白なら中止-------------------------------------------------------------------------------
if (textBoxドロップパス.Text == "")
{
return;
}
//1)エクセル読み込み-------------------------------------------------------------------------------------
//ht[参考]tps://www.ipentec.com/document/csharp-open-read-excel-book-and-sheet
//改行記号を削除して代入
string ExcelBookFileName = textBoxドロップパス.Text.Replace(Environment.NewLine, "");
ExcelBookFileName = ExcelBookFileName.Replace("\\", "\\\\");
//Console.WriteLine("加工後:" + ExcelBookFileName);
//DataTbleの準備
System.Data.DataTable dt = new System.Data.DataTable();
DataRow dr;
//年月日のDistinctを求める為のDictionary
var dic年月日 = new Dictionary<string, string>(); //Key:年月日, Value:年月日
//DataTableカラム追加/定義
dt.Columns.Add("社員番号", typeof(string));
dt.Columns.Add("氏名", typeof(string));
dt.Columns.Add("性別", typeof(string));
//これからエクセル読み込み!
var excelApplication = new Microsoft.Office.Interop.Excel.Application();
try
{
Workbooks workbooks = excelApplication.Workbooks;
try
{
Workbook workbook = workbooks.Open(ExcelBookFileName);
try
{
Sheets worksheets = workbook.Sheets;
try
{
//Worksheet worksheet = worksheets[1];
//の様に番号でしかシートを指定できないので↓↓↓
//1) シート名からシートインデックスを探す(一発の関数は無いみたい(TT))
int sheetId = -1;
int m = 0;
foreach (Worksheet sh in worksheets)
{
Console.WriteLine("-----m:" + m.ToString() + " / " + sh.Name);
m += 1;
if (sh.Name == "Sheet1")
{
sheetId = m;
}
}
if (sheetId == -1)
{
MessageBox.Show("[Sheet1]シートが見つかりません。\n前後に半角スペース等が入っていませんか?\n確認ください。");
}
//2) 対象シートを読込む
Worksheet worksheet = worksheets[sheetId]; //読込対象のシートを指定!!!
try
{
// 使用範囲を一括で二次元配列にコピー
Console.WriteLine("-----これから[使用範囲を一括で二次元配列にコピー]");
Object[,] rangeArray;
Range usedRange = worksheet.UsedRange;
try
{
rangeArray = usedRange.Value;
}
finally
{
Marshal.ReleaseComObject(usedRange);
}
//Console.WriteLine("-----これから[(テスト)配列の並び確認]");
//(テスト)配列の並び確認
//Console.WriteLine("rangeArray[5,2].ToString(): " + rangeArray[5, 2].ToString());
//(テスト) 配列要素のNull判別の方法
// rangeArray[2, 1].ToString()); の元ファイルは空白、配列化するとNullが入入る。
//if (rangeArray[2, 1] == null)
//{
// Console.WriteLine("Nullです。");
//}
//else
//{
// Console.WriteLine("Nullではありません。");
//}
//2次元配列の長さ
int lastRow = rangeArray.GetLength(0); //1次元
int lastCol = rangeArray.GetLength(1); //2次元
Console.WriteLine("lastRow:" + lastRow);
Console.WriteLine("lastCol:" + lastCol);
//更新日時取得
DateTime 更新日時 = DateTime.Now;
// 二次元配列をループを回しながらdtに格納する。
//ヘッダー無し int i = 0;
//ヘッダーあり int i = 1;
for (int i = 0; i < lastRow; i++)
{
//Console.WriteLine("i:" + i.ToString());
errorRow = i + 1;
dr = dt.NewRow();
if (rangeArray[1 + i, 1] == null)
{
dr["社員番号"] = "";
}
else
{
dr["社員番号"] = rangeArray[1 + i, 1].ToString();
}
if (rangeArray[1 + i, 2] == null)
{
dr["氏名"] = "";
}
else
{
dr["氏名"] = rangeArray[1 + i, 2].ToString();
}
if (rangeArray[1 + i, 3] == null)
{
dr["性別"] = "";
}
else
{
dr["性別"] = rangeArray[1 + i, 3].ToString();
}
dt.Rows.Add(dr);
}
}
finally
{
Marshal.ReleaseComObject(worksheet);
Console.WriteLine("---------------【完了】Marshal.ReleaseComObject(worksheet);");
}
}
catch
{
error = "有";
MessageBox.Show("ファイルの読み込みに失敗しました。" +
errorRow.ToString() + "行目のデータに問題があります。" +
"[catch/worksheet]");
}
finally
{
Marshal.ReleaseComObject(worksheets);
Console.WriteLine("---------------【完了】Marshal.ReleaseComObject(worksheets);");
}
}
finally
{
if (workbook != null)
{
workbook.Close(false);
}
Marshal.ReleaseComObject(workbook);
Console.WriteLine("---------------【完了】Marshal.ReleaseComObject(workbook);");
}
}
finally { Marshal.ReleaseComObject(workbooks); }
}
catch
{
error = "有";
}
finally
{
if (excelApplication != null)
{
excelApplication.Quit();
}
Marshal.ReleaseComObject(excelApplication);
Console.WriteLine("---------------【完了】Marshal.ReleaseComObject(excelApplication);");
}
if (error == "有")
{
Console.WriteLine("ファイルの読込に失敗しました。");
return;
}
//2.dataGridView1への登録と設定-----------------------------------------------------------------------------
//dataGridView1にセットする。
dataGridView1.DataSource = dt;
//dataGridView1の設定
//ユーザの操作規制 ←これはFormのLoadへ持って行っても良い
dataGridView1.ReadOnly = true; //読取専用
dataGridView1.AllowUserToDeleteRows = false; //行削除禁止
dataGridView1.AllowUserToAddRows = false; //行挿入禁止
dataGridView1.AllowUserToResizeRows = false; //行の高さ変更禁止
dataGridView1.RowHeadersVisible = false; //行ヘッダーを非表示にする
dataGridView1.MultiSelect = false; //セル、行、列が複数選択禁止
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; //セルを選択すると行全体が選択されるようにする
//並び替えができないようにする
foreach (DataGridViewColumn c in dataGridView1.Columns)
c.SortMode = DataGridViewColumnSortMode.NotSortable;
//基本フォントの設定
dataGridView1.DefaultCellStyle.Font = new System.Drawing.Font("MS UI Gothic", 10);
//ヘッダーの色等
dataGridView1.EnableHeadersVisualStyles = false; // Visualスタイルを使用しない
dataGridView1.ColumnHeadersDefaultCellStyle.BackColor = Color.LightGray;
dataGridView1.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("MS UI Gothic", 9);
dataGridView1.ColumnHeadersHeight = 20;
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
//カラム幅設定
dataGridView1.Columns["社員番号"].Width = 80;
dataGridView1.Columns["氏名"].Width = 250;
dataGridView1.Columns["性別"].Width = 250;
//読み込まないRowをグレーにする(ここではシート上の3行目からデータ部が始まるとする)
for (int i = 0; i < 3 - 1; i++)
{
dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Gainsboro;
}
}