728x90

Key_Down 이벤트에 아래와 같이 코드를 추가해주면 엔터키를 쳤을 때 다음 행으로 이동이 안된다.

구글에서 c# datagridview cell enter event 로 검색하면 관련 게시글들이 나온다.


private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyData == Keys.Enter)
    {
        int column = dataGridView1.CurrentCell.ColumnIndex;
        int row = dataGridView1.CurrentCell.RowIndex;
        dataGridView1.CurrentCell = dataGridView1[column, row];
        e.Handled = true;
    }
}


엔터키를 치면 행으로 이동하지 않고 칼럼으로 이동하고 마지막 칼럼에서는 다음행의 첫번째 칼럼으로 이동하게 하는 코드

private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyData == Keys.Enter)
    {
        e.SuppressKeyPress = true;
        int column = dataGridView1.CurrentCell.ColumnIndex;
        int row = dataGridView1.CurrentCell.RowIndex;
        if (column == dataGridView1.Columns.Count -1)
        {
            dataGridView1.CurrentCell = dataGridView1[0, row + 1];
        }
        else
        {
            dataGridView1.CurrentCell = dataGridView1[column + 1, row];
        }
    }
}

블로그 이미지

Link2Me

,
728x90

C# Context Menu 를 만들 때 서브 메뉴가 보이거나 보이지 않게 처리하는 방법이다.

마우스 우클릭을 해서 보이는 Context Menu 를 칼럼에 따라 메뉴가 보이게, 안보이게 처리하는 걸 시도해봤다.

Context Menu 는 메뉴 생성하는 곳에서 생성을 했다. 순서를 변경하는 걸 해보려고 했더니 안된다.

메뉴를 보이게 보이지 않게 처리하는 것은 Visible = true, false 로 선택 옵션을 준다.

dataGridView1 에서 필요해서 CellMouseClick 이벤트를 등록한 다음에

아래와 같이 메뉴를 선택적으로 if 조건을 주면 칼럼에서 메뉴가 다르게 보인다.

보여줘야 할 메뉴가 너무 많다면 이런 방법을 시도해보는 것도 좋을 것이다.


private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.ColumnIndex == 1)
    {
        NaverToolStripMenuItem1.Visible = true;
        DaumToolStripMenuItem.Visible = true;
        GoogleToolStripMenuItem.Visible = true;
        toolStripMenuItem11.Visible = true;
    }
    else if (e.ColumnIndex == 2)
    {
        NaverToolStripMenuItem1.Visible = false;
        DaumToolStripMenuItem.Visible = true;
        GoogleToolStripMenuItem.Visible = true;
        toolStripMenuItem11.Visible = false;
    }
    else
    {
        NaverToolStripMenuItem1.Visible = false;
        DaumToolStripMenuItem.Visible = false;
        GoogleToolStripMenuItem.Visible = false;
        toolStripMenuItem11.Visible = false;
    }
}


칼럼에 따라 Context Menu 를 동적으로 생성하는 것도 나중에 한번 해봐야겠다.


블로그 이미지

Link2Me

,
728x90

dataGridView cell 에 툴팁이 보이게 하는 걸 알고 싶어 테스트를 해봤다.

두가지 모두 정상적으로 잘 동작되었다.


방법 1

private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
    dataGridView1.CellToolTipTextNeeded += new DataGridViewCellToolTipTextNeededEventHandler(dataGridView1_CellToolTipTextNeeded);
}

void dataGridView1_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e)
{
    if (e.ColumnIndex == this.dataGridView1.Columns["Price"].Index)
    {
        e.ToolTipText = this.dataGridView1.Rows[e.RowIndex].Cells[3].Value.ToString();
    }
}


방법2
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if ((e.ColumnIndex == this.dataGridView1.Columns["Price"].Index) && e.Value != null)
    {
        DataGridViewCell cell = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
        cell.ToolTipText = this.dataGridView1.Rows[e.RowIndex].Cells[3].Value.ToString();
    }
}


일반적인 툴팁 사용은

MouseHover 이벤트를 발생시켜 보여주고 싶은 메시지를 보여주면 된다.

private void expandSearch_MouseHover(object sender, EventArgs e)
{

    toolTip1.IsBalloon = true;  // 풍선도움말 모양으로

    toolTip1.SetToolTip(expandSearch, "전체 DB 대상 검색");
}


툴팁은 0.5초 후에 나타나고 5초뒤에 사라지는 것이 기본이다.

프로그램이 Load 될 때에 보여주고 싶은 툴팁을 지정해줘도 된다.


블로그 이미지

Link2Me

,
728x90

MySQL 데이터 Update 를 하면서 화면 갱신 문제처리에 부딪쳤다. 현재 작업하는 화면을 거의 유지하면서 MySQL 데이터 Update 를 해야 한다.


데이터 업데이트후 MySQL 다시 조회(Select) 루틴으로 하면 매번 화면의 current cell 상태를 잃어버린다. 이러다보니 너무 번거롭고 귀찮다.


foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
    string uid = row.Cells[2].Value.ToString();
    MessageBox.Show("index :" + row.Index.ToString() + " uid : " + uid);
    dataGridView1.Rows.RemoveAt(row.Index);  // 셀 삭제
}


선택된 행만 셀삭제 처리를 해보니까 선택된 행은 모두 삭제되고 마지막 셀 바로 이전셀이 자동으로 현재의 셀로 선택된다.


int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
int rowIndex = dataGridView1.CurrentCell.RowIndex;


CurrentCell 의 값을 가지고 작업해보면 항상 마지막에 선택된 셀의 값만 반환한다.

따라서 이건 원하는 결과를 만들어주지 못해서 패스.


FullRowSelect 로 하다보니 화면에서 보기가 별로 안좋다.

그래서 CellSelect 방식으로 테스트를 해봤다.


foreach (DataGridViewCell row in dataGridView1.SelectedCells)
{
    string uid = dataGridView1.Rows[row.RowIndex].Cells[2].Value.ToString();
    MessageBox.Show("index :" +
row.RowIndex.ToString()+ " uid : " + uid);
    dataGridView1.Rows.RemoveAt(
row.RowIndex);  // 셀 삭제
}


셀 단위이지만 선택된 셀의 RowIndex 를 구하면 원하는 행의 값을 얻어낼 수가 있다.


셀 단위로 선택하면 오류를 범하기 쉬운 문제를 방지하기 위해서 특정한 칼럼만 선택될 때 동작하도록 if 문을 추가했다.

foreach (DataGridViewCell row in dataGridView1.SelectedCells)
{
    if (row.ColumnIndex == 3)
    {
        string uid = dataGridView1.Rows[row.RowIndex].Cells[2].Value.ToString();
        dataGridView1.Rows.RemoveAt(row.RowIndex);  // 셀 삭제
    }
}


테스트를 해보고 나서 MySQL DB와 연결해서 작업을 했더니 완벽하게 원하는 결과가 나온다.

private void CheckedData(DataGridView dgv, int checkingcode)
{
    myConn = new MySqlConnection(GetConnectionString());
    if (myConn.State == ConnectionState.Closed)
    {
        myConn.Open();
    }

    try
    {
        foreach (DataGridViewCell row in dgv.SelectedCells)
        {
            if (row.ColumnIndex == 3)
            {
                string uid = dgv.Rows[row.RowIndex].Cells["uid"].Value.ToString();
                string content = dgv.Rows[row.RowIndex].Cells["content"].Value.ToString();

                if (content == null || content.Equals("")) { continue; }
                string strqry = string.Format("UPDATE data SET checkingcode={0}, content='{1}' Where uid ={2}", checkingcode, content.Trim(), uid);
                MySqlCommand cmd = new MySqlCommand(strqry, myConn);
                cmd.ExecuteNonQuery();
                cmd.Dispose();
                dgv.Rows.RemoveAt(row.RowIndex);  // 셀 삭제
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        if (myConn.State == ConnectionState.Open)
        {
            myConn.Close();
        }
    }
}


블로그 이미지

Link2Me

,
728x90

C# 에서 사용하는 DataGridView의 폰트를 각각의 부분에 지정할수 있다.


// 전체적으로 폰트 적용하기
this.dataGridView1.Font = new Font("Tahoma", 10, FontStyle.Regular);

// Colum 의 해더부분을 지정하기
this.dataGridView1.ColumnHeadersDefaultCellStyle.Font = new Font("Tahoma", 10, FontStyle.Bold);

// Row 해더부분을 지정하기
this.dataGridView1.RowHeadersDefaultCellStyle.Font = new Font("Tahoma", 10, FontStyle.Bold);

// Cell 내용부분을 지정하기
this.dataGridView1.DefaultCellStyle.Font = new Font("Tahoma", 10, FontStyle.Bold);

블로그 이미지

Link2Me

,
728x90

C# dataGridView 에 엑셀파일을 읽어들일 때 엑셀 파일의 형식인지를 체크하여 엑셀파일이 아닌 것은 사전에 차단하는 기능이 추가된 엑셀 읽어들이는 코드이다.


엑셀 파일 형식 검사하는 코드는 인터넷 서칭하다가 발견했는데 그분의 블로그가 당장은 생각나지 않는다.

형식검사하는 것은 간단하게 파악할 수가 있다.

HEX View 파일(http://link2me.tistory.com/807)을 설치해서 파일을 Drag & Drop 하면 헤더부분에서 엑셀파일인지 아닌지를 판별할 수가 있다.

임의로 다른 파일을 엑셀로 확장자를 변경해도 실제는 엑셀 파일이 아니므로 걸러낼 수가 있다.


형식검사하는 걸 응용하면 Encoding 검사할 수도 있다.


private void btnExcelRead_Click(object sender, EventArgs e)
{
    try
    {
        // 파일 선택창 객체를 생성
        using (OpenFileDialog dlg = new OpenFileDialog())
        {
            dlg.Filter = "Excel Files(2007이상)|*.xlsx|Excel Files(97~2003)|*.xls";
            dlg.InitialDirectory = @"C:\test\";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                ImportExcelData_Read(dlg.FileName, dataGridView1); // dataGridView에 데이터를 세팅 메서드 호출
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }           
}

public static DataSet ImportExcelData_Read(string fileName, DataGridView dgv)
{
    // 엑셀 문서 읽어서 dataGridView 에 출력하기
    string connectionString = string.Empty;

    if (File.Exists(fileName))
    {
        int ExcelType = ExcelFileType(fileName);  // 엑셀파일 형식 검사
        switch (ExcelType)
        {
            case (-2): throw new Exception(fileName + "의 형식검사중 오류가 발생하였습니다.");
            case (-1): throw new Exception(fileName + "은 엑셀 파일형식이 아닙니다.");
            case (0):
                connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0};Extended Properties='Excel 8.0';", fileName);
                break;
            case (1):
                connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0};Extended Properties='Excel 12.0';", fileName);
                break;
        }
    }

    DataSet DS = new DataSet();

    string strQuery = "SELECT * FROM [Sheet1$]";
    OleDbConnection oleDBConn = new OleDbConnection(connectionString);
    oleDBConn.Open();

    OleDbCommand oleCmd = new OleDbCommand(strQuery, oleDBConn);
    OleDbDataAdapter dataAdapter = new OleDbDataAdapter(oleCmd);

    DataTable dataTable = new DataTable();
    dataAdapter.Fill(dataTable);
    DS.Tables.Add(dataTable);

    dgv.DataSource = DS.Tables[0].DefaultView;

    // 데이터에 맞게 칼럼 사이즈 조정하기
    for (int i = 0; i < dgv.Columns.Count; i++)
    {
        dgv.AutoResizeColumn(i, DataGridViewAutoSizeColumnMode.AllCells);
    }
    dgv.AllowUserToAddRows = false;  // 빈레코드 표시 안하기
    dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;
    //dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; // 화면크기에 맞춰 채우기

    dataTable.Dispose();
    dataAdapter.Dispose();
    oleCmd.Dispose();

    oleDBConn.Close();
    oleDBConn.Dispose();

    return DS;
}

#region 엑셀파일 형식
public static int ExcelFileType(string XlsFile)
{
    byte[,] ExcelHeader = {
        { 0xD0, 0xCF, 0x11, 0xE0, 0xA1 }, // XLS  File Header
        { 0x50, 0x4B, 0x03, 0x04, 0x14 }  // XLSX File Header
    };

    // result -2=error, -1=not excel , 0=xls , 1=xlsx
    int result = -1;

    FileInfo FI = new FileInfo(XlsFile);
    FileStream fs = FI.Open(FileMode.Open);

    try
    {
        byte[] buffer = new byte[5];
        fs.Read(buffer, 0, 5);
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 5; j++)
            {
                if (buffer[j] != ExcelHeader[i, j]) break;
                else if (j == 4) result = i;
            }
            if (result >= 0) break;
        }
    }
    catch
    {
        result = (-2);
    }
    finally
    {
        fs.Close();
    }
    return result;
}
#endregion



블로그 이미지

Link2Me

,
728x90

C# 에서 dataGridView 내용을 CSV 파일로 내보내기하는 코드이다.

CSV 파일은 텍스트 파일 내보내기와 동일하다.

기존 파일이 존재하는데 덮어쓰기 시도하면 덮어쓰기 된다.


private void btnCSV_Save_Click(object sender, EventArgs e)
{
    using (SaveFileDialog dlg = new SaveFileDialog())
    {
        dlg.Filter = "csv (*.csv) | *.csv";
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            this.Save_Csv(dlg.FileName, dataGridView1); // dataGridView에 데이터를 세팅하는 메서드를 호출
        }
    }
}


/// <summary>
/// dataGridView 데이터를 CSV 로 파일 내보내기
/// </summary>
private void Save_Csv(string fileName, DataGridView dgv, bool header)
{
    string delimiter = ";";  // 구분자
    FileStream fs = new FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);
    StreamWriter csvExport = new StreamWriter(fs, System.Text.Encoding.UTF8);

    if (dgv.Rows.Count == 0) return;

    // 헤더정보 출력
    if (header)
    {
        for (int i = 0; i < dgv.Columns.Count; i++)
        {
            csvExport.Write(dgv.Columns[i].HeaderText);
            if (i != dgv.Columns.Count - 1)
            {
                csvExport.Write(delimiter);
            }
        }
    }

    csvExport.Write(csvExport.NewLine); // add new line

    // 데이터 출력
    foreach (DataGridViewRow row in dgv.Rows)
    {
        if (!row.IsNewRow)
        {
            for (int i = 0; i < dgv.Columns.Count; i++)
            {
                csvExport.Write(row.Cells[i].Value);
                if (i != dgv.Columns.Count - 1)
                {
                    csvExport.Write(delimiter);
                }
            }
            csvExport.Write(csvExport.NewLine); // write new line
        }
    }
   
    csvExport.Flush(); // flush from the buffers.
    csvExport.Close();
    fs.Close();
    MessageBox.Show("CSV파일 저장 완료!");
}





블로그 이미지

Link2Me

,
728x90

dataGridView 의 화면 높이를 자동으로 설정했더니 보기가 좋지 않아서 수동으로 높이를 조정했다.

자동 설정하는 옵션은

dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;


수동 지정 방법은


Font Size 변경



블로그 이미지

Link2Me

,
728x90

C# dataGridView 에서 OleDB 를 이용하여 엑셀로 내보내기 구현하면서 엄청 생고생을 많이 했다. 처음부터 그냥 단순하게 시작해서 잘 동작되는지 확인하고 했어야 하는데 검색해서 찾아낸 소스가 좋아보여서 그걸 분석하면서 해본다고 하다가 시간만 엄청 소모했다.

엑셀 내보내기, 가져오기 괜찮은 블로그 : http://blog.naver.com/exila 이 사이트는 DataTable 과 DataSet 을 활용하고 OleDB 를 이용하여 엑셀 파일로 저장하는 로직이다.

내가 아직 DataSet 을 이용하는 걸 완벽하게 이해를 못해서 활용하기에는 부담스러웠다.

그리고 난 그냥 dataGridView 화면 출력상에서 보이는 걸 가지고 내보내기를 해보고 싶었다.

이 코드는 완벽하게 동작한다고 할 수가 없다. 기능 동작이 안되는게 아니라 파일 덮어쓰기를 하면 이미 Sheet1 테이블이 존재한다고 하면서 에러가 난다. 이런 부분 등을 고려하여 더 보완을 해야 한다.

엑셀 2003 이하버전으로 저장을 하면 문제없이 저장이 되는데 엑셀 2007 이상으로 저장하면 파일 인식을 잘 못한다. 이 부분도 개선을 해야 한다.
'Excel 12.0;HDR=No' 다.


일일이 값을 찍어주는 걸 하면서 확인 작업을 했다.

string strquery = string.Format("INSERT INTO [Sheet1$] values({0},{1},'{2}',{3},{4})", dgv.Rows[r].Cells[0].Value, dgv.Rows[r].Cells[1].Value, dgv.Rows[r].Cells[2].Value, dgv.Rows[r].Cells[3].Value, dgv.Rows[r].Cells[4].Value);


다.

Sheet 다. 다.

if (File.Exists(fileName))
{
    File.Delete(fileName);  // 기존 파일에 기록을 하려면 이렇게 삭제하고 다시 생성해야 정상 동작됨
}


이제 남은 것은 엑셀 2007 이상으로 저장할 때 정상 저장이 되도록 하는 부분을 검토해야 한다.



// ---------------------------------- 드 --------------------------//

private void btnExcelSave_Click(object sender, EventArgs e)
{
    try
    {
        using (SaveFileDialog dlg = new SaveFileDialog())
        {
            dlg.Filter = "Excel Files(97~2003)|*.xls|Excel Files(2007이상)|*.xlsx";
            dlg.InitialDirectory = @"C:\test\";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                dataGridView_ExportToExcelSave(dlg.FileName, dataGridView2);
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}


private void dataGridView_ExportToExcelSave(string fileName, DataGridView dgv)
{


    if (File.Exists(fileName))
    {
        File.Delete(fileName);  // 기존 파일에 기록을 하려면 이렇게 삭제하고 다시 생성해야 정상 동작됨
    }


    string connectionString = string.Empty;
    try
    {
        if (Path.GetExtension(fileName).ToLower() == ".xls")
        {
            connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0};Mode=ReadWrite;Extended Properties='Excel 8.0;HDR=No';", fileName);
        }
        else if (Path.GetExtension(fileName).ToLower() == ".xlsx")
        {
            connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0};Mode=ReadWrite;Extended Properties='Excel 12.0;HDR=No';", fileName);
        }

        OleDbConnection oleDBConn = new OleDbConnection(connectionString);
        oleDBConn.Open();

        // Header 라인 생성
        StringBuilder Header_Column = new StringBuilder();
        for (int i = 0; i < dgv.Columns.Count; i++)
        {
            if (Header_Column.Length > 0) Header_Column.Append(",");
            Header_Column.Append("[" + dgv.Columns[i].HeaderText + "] CHAR(255)");
        }
        OleDbCommand Cmd = new OleDbCommand("CREATE TABLE [Sheet1] (" + Header_Column.ToString() + ")", oleDBConn);
        Cmd.ExecuteNonQuery();

        // 본문 내용 출력
        for (int r = 0; r < dgv.Rows.Count; r++)
        {
            StringBuilder Values = new StringBuilder();
            for (int i = 0; i < dgv.Columns.Count; i++)
            {
                if (Values.Length > 0) Values.Append(",");
                Values.Append("'" + dgv.Rows[r].Cells[i].Value.ToString() + "'");
            }
            string strquery = "INSERT INTO [Sheet1$] values(" + Values.ToString() + ")";        
            Cmd = new OleDbCommand(strquery, oleDBConn);
            Cmd.ExecuteNonQuery();
        }
        if (oleDBConn.State == ConnectionState.Open)
        {
            oleDBConn.Close();  // 연결 종료
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }           
}

'C# > dataGridView' 카테고리의 다른 글

C# datagGridView CSV 파일로 내보내기  (0) 2015.12.05
C# dataGridView 높이 변경  (0) 2015.10.18
C# dataGridView 에 엑셀 읽어들이기  (0) 2015.10.07
C# dataGridView 엑셀로 내보내기  (2) 2015.10.07
C# dataGridView 행 삭제  (0) 2015.10.05
블로그 이미지

Link2Me

,
728x90

꼼꼼하게 테스트 해보느라고 시간이 상당히 걸렸다. 엑셀파일이 이미 열려 있는 경우에는 프로그램에서 실행하지 못하고 에러가 발생할 수 있다. 이 부분을 try { } catch { } 로 처리를 안해주면 문제가 생길 수 있다는 걸 알았다.


Microsoft.ACE.OLEDB.12.0' 공급자는 로컬 컴퓨터에 등록할 수 없습니다.
라는 예외가 발생 했을 경우 불러오려는 엑셀의 형식을 기존에 설치된 드라이버가 인식하지 못할 경우 발생하는 에러다.
http://www.microsoft.com/ko-kr/download/details.aspx?id=13255
에서 설치한 오피스(엑셀)버전을 체크하여 드라이버를 다운로드 받아서 설치해준다.


Microsoft.Jet.OLEDB.4.0 은 32 bit 에서만 동작되므로 빌드할 때 64비트로 하면 에러가 발생한다.

프로젝트 - 속성에서 아래와 같이 변경해주어야 한다.




다.
using System.Data.OleDb; // OLEDB 를 이용한 엑셀 읽기, 수정, 삭제 등 처리 가능

private void btnExcelRead_Click(object sender, EventArgs e)
{
    try
    {
        using (OpenFileDialog dlg = new OpenFileDialog()) // 파일 선택창 객체를 생성
        {
            dlg.Filter = "Excel Files(2007이상)|*.xlsx|Excel Files(97~2003)|*.xls";
            dlg.InitialDirectory = @"C:\test\";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                ImportExcelData_Read(dlg.FileName, dataGridView2); // 메서드를 호출
            }
        }
    }
    catch (Exception ex)  // 엑셀파일이 다른 프로그렘에서 이미 열었거나 에러가 발생하면 에러를 출력해준다.
    {
        MessageBox.Show(ex.Message);
    }           
}

public void ImportExcelData_Read(string fileName, DataGridView dgv)
{
    // 엑셀 문서 내용 추출
    string connectionString = string.Empty;

    if (File.Exists(fileName))  // 파일 확장자 검사
    {
        if (Path.GetExtension(fileName).ToLower() == ".xls")
        {   // Microsoft.Jet.OLEDB.4.0 은 32 bit 에서만 동작되므로 빌드할 때 64비트로 하면 에러가 발생함.
            connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0};Extended Properties=Excel 8.0;", fileName);
        }
        else if (Path.GetExtension(fileName).ToLower() == ".xlsx")
        {
            connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0};Extended Properties=Excel 12.0;", fileName);
        }
    }

    DataSet data = new DataSet();

    string strQuery = "SELECT * FROM [Sheet1$]";  // 엑셀 시트명 Sheet1의 모든 데이터를 가져오기
    OleDbConnection oleConn = new OleDbConnection(connectionString);
    oleConn.Open();

    OleDbCommand oleCmd = new OleDbCommand(strQuery, oleConn);
    OleDbDataAdapter dataAdapter = new OleDbDataAdapter(oleCmd);

    DataTable dataTable = new DataTable();
    dataAdapter.Fill(dataTable);
    data.Tables.Add(dataTable);

    dgv.DataSource = data.Tables[0].DefaultView;

    // 데이터에 맞게 칼럼 사이즈 조정하기
    for (int i = 0; i < dgv.Columns.Count; i++)
    {
        dgv.AutoResizeColumn(i, DataGridViewAutoSizeColumnMode.AllCells);
    }
    dgv.AllowUserToAddRows = false;  // 빈레코드 표시 안하기
    dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;
    //dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; // 화면크기에 맞춰 채우기

    dataTable.Dispose();
    dataAdapter.Dispose();
    oleCmd.Dispose();

    oleConn.Close();
    oleConn.Dispose();
}



소스코드와 다른 코드가 같이 포함된 파일

import_exceldata.cs


블로그 이미지

Link2Me

,
728x90

C# dagaGridView 에서 데이터를 엑셀로 내보내기하는 걸 테스트를 해보고 정상 저장되는 걸 확인하고 적어둔다.

// 엑셀로 데이터를 내보내기
// SaveFileDialog 를 사용해야 폴더 특성을 타지 않고 저장이 가능하다.
// @"C:\test.xls" 라고 직접 파일명을 적어주면 파일 저장권한이 없다고 에러가 발생한다.


export_to_excel.cs


Microsoft.Office.Interop.Excel https://msdn.microsoft.com/ko-kr/library/dd264733.aspx 다.





private void submiExcel_Click(object sender, EventArgs e)
{
    SaveFileDialog sfd = new SaveFileDialog();
    sfd.Title = "Save as Excel File";
    sfd.Filter = "Excel Files(2003)|*.xls|Excel Files(2007)|*.xlsx";
    sfd.FileName = "";
    if (sfd.ShowDialog() == DialogResult.OK)
    {
        dataGridView_ExportToExcel(sfd.FileName, dataGridView1);
    }
}

// using System.Data;
// using Excel = Microsoft.Office.Interop.Excel;
private void dataGridView_ExportToExcel(string fileName, DataGridView dgv)
{
    Excel.Application excelApp = new Excel.Application();
    if (excelApp == null)
    {
        MessageBox.Show("엑셀이 설치되지 않았습니다");
        return;
    }
    Excel.Workbook wb = excelApp.Workbooks.Add(true);
    Excel._Worksheet workSheet = wb.Worksheets.get_Item(1) as Excel._Worksheet;  
    workSheet.Name = "C#";

    if (dgv.Rows.Count == 0)
    {
        MessageBox.Show("출력할 데이터가 없습니다");
        return;
    }

    // 헤더 출력
    for (int i = 0; i < dgv.Columns.Count - 1; i++)
    {
        workSheet.Cells[1, i + 1] = dgv.Columns[i].HeaderText;
    }

    //내용 출력
    for (int r = 0; r < dgv.Rows.Count; r++)
    {
        for (int i = 0; i < dgv.Columns.Count - 1; i++)
        {
            workSheet.Cells[r + 2, i + 1] = dgv.Rows[r].Cells[i].Value;
        }
    }


    workSheet.Columns.AutoFit(); // 글자 크기에 맞게 셀 크기를 자동으로 조절


    // 엑셀 2003 으로만 저장이 됨
    wb.SaveAs(fileName, Excel.XlFileFormat.xlWorkbookNormal, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
        Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

    wb.Close(Type.Missing, Type.Missing, Type.Missing);
    excelApp.Quit();
    releaseObject(excelApp);
    releaseObject(workSheet);
    releaseObject(wb);
}

#region 메모리해제
private static void releaseObject(object obj)
{
    try
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
        obj = null;
    }
    catch (Exception e)
    {
        obj = null;
    }
    finally
    {
        GC.Collect();
    }
}
#endregion


블로그 이미지

Link2Me

,
728x90

dataGridView 에서 행 삭제 함수 구현


private void DeleteRowToolStripMenuItem_Click(object sender, EventArgs e)
{
    // Line(행) 삭제
    Delete_dataGridView(dataGridView1);
}

private void Delete_dataGridView(DataGridView dgv)
{
    // Line(행) 삭제
    foreach (DataGridViewRow dgr in dgv.SelectedRows)
    {
        dgv.Rows.Remove(dgr);
    }
}

블로그 이미지

Link2Me

,
728x90

C# dataGridView 에서 현재 셀의 속성을 이용하여 키보드가 Up 될(커서가 위치할) 때 해당 값을 텍스트박스로 출력하는 방법이다.



int columnIndex = dataGridView.CurrentCell.ColumnIndex;
int rowIndex = dataGridView.CurrentCell.RowIndex;

을 이용하는 것도 좋지만,

int rowIndex = dataGridView1.CurrentRow.Index; 를 사용하는게 더 좋은거 같다.

추가적으로

lbl_View1.Text = this.dataGridView1[dataGridView1.CurrentCell.ColumnIndex, dataGridView1.CurrentRow.Index].Value.ToString();

현재의 셀의 값을 읽어내는 것은 dataGridView1[칼럼,행] 으로 표기된다.

이걸 잘못해서 거꾸로 적었다가 낭패를 본 적도 있다.

셀 단위로 이동할 경우 자동으로 현재의 셀 값을 읽어낸다.


private void dataGridView1_KeyUp(object sender, KeyEventArgs e)
{
     int rowIndex = dataGridView1.CurrentRow.Index;

     textBox1.Text = dataGridView1.Rows[rowIndex].Cells[3].Value.ToString();
     textBox2.Text = dataGridView1.Rows[rowIndex].Cells[4].Value.ToString();
     textBox3.Text = dataGridView1.Rows[rowIndex].Cells[5].Value.ToString();
     textBox4.Text = dataGridView1.Rows[rowIndex].Cells[6].Value.ToString();
}


열(column) 의표시를 dataGridView 에서는 Cells 로 표현한다.

만약, 현재 커서가 위치한 셀의 값만 textBox1.Text 에 표시하고 싶다면


private void dataGridView1_KeyUp(object sender, KeyEventArgs e)
{
     int rowIndex = dataGridView1.CurrentCell.RowIndex;

     int columnIndex = dataGridView1.CurrentCell.ColumnIndex;

     textBox1.Text = dataGridView1.Rows[rowIndex].Cells[columnIndex].Value.ToString();
}


// 현재 dataGridView 셀의 값을 표기

if (dgv == dataGridView1)
{
    lbl_View1.Text = dgv[dgv.CurrentCell.ColumnIndex, dgv.CurrentRow.Index].Value.ToString();
}
else if (dgv == dataGridView2)
{
    lbl_View2.Text = dgv[dgv.CurrentCell.ColumnIndex, dgv.CurrentRow.Index].Value.ToString();
}



블로그 이미지

Link2Me

,
728x90

엑셀처럼 셀을 클릭하면 해당 셀을 상단의 공간에 보여주기 위한 용도로 활용해봤다.


private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
       lbl_View.Text = this.dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString();
}


// MouseDown 이벤트 : 마우스 포인터가 컨트롤 위에 있을 때 마우스 단추를 클릭하면 발생

private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
    lbl_View1.Text = this.dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString();
}


// MouseClick 이벤트 : 컨트롤을 마우스로 클릭할 때 발생

블로그 이미지

Link2Me

,
728x90

원하는 칼럼에 자동 번호 매기는 소스를 열심히 찾아봤더니 모 블로그에 나온 것은 오직 첫번째 칼럼에만 Numbering 이 된다.


구글링을 해봤더니 간단한 소스가 검색된다.


private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
      // 원하는 칼럼에 자동 번호 매기기
      this.dataGridView1.Rows[e.RowIndex].Cells[1].Value = (e.RowIndex + 1).ToString();          
}





블로그 이미지

Link2Me

,
728x90

dataGridView 의 각 Row를 선택할 때 칼럼의 값을 Textbox 에 보여주도록 하려면 어떻게 해야 할까?



나같은 초보자는 아래 코드를 어떻게 만드는지를 모른다.

dataGridView1 의 속성 Event 창에서 더블클릭하면 자동으로 코드를 채울 수 있게 만들어진다.

필요한 코드만 직접 작성하면 된다.


//셀 내용 읽기 1행, 0열  --> 행은 Rows, 열은 Column 이 아니라 Cells 로 표기하네

dataGridView1.Rows[1].Cells[0].Value.ToString();



private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    textBox1.Text = dataGridView1.Rows[e.RowIndex].Cells[3].Value.ToString();
    textBox2.Text = dataGridView1.Rows[e.RowIndex].Cells[4].Value.ToString();
    textBox3.Text = dataGridView1.Rows[e.RowIndex].Cells[5].Value.ToString();
    textBox4.Text = dataGridView1.Rows[e.RowIndex].Cells[6].Value.ToString();

    if (e.ColumnIndex == 2)  // 3번째 칼럼이 선택되면....
    {
        MessageBox.Show((e.RowIndex + 1) + "  Row  " + (e.ColumnIndex + 1) + "  Column button clicked ");
    }
}



만약, 외국 사이트, 블로그 등에 나온 자료를 보고 사용자 소스코드에 붙여넣기를 한 경우에는

디자이너 소스 파일에는 기록이 안되어 있다. 그러므로 Event 연결을 해줘야 한다.

위의 코드를 보면 CellClick 이라고 보일 것이다.

바로 이 부분을 연결하기 위해서 Shift + F7 키를 눌러서 WindowsForm 화면으로 이동한 다음에

dataGridView1 을 마우스로 선택하고 나서 속성창에서 Event 를 클릭한 다음에 CellClick 이벤트를 찾는다.



이렇게 해주면 연결되어 동작이 된다.


글 쓰려고 테스트한다고 2번을 빈칸으로 지웠더니 CellClick 이벤트 소스 코드가 삭제되어 버렸다.

혹시 이런 증상이 생길지 모르니 소스코드는 EditPlus 같은 텍스트편집기에 복사를 해주는게 좋다.

블로그 이미지

Link2Me

,
728x90

인터넷 열심히 뒤지면서 알아내고 직접 테스트해본 걸 적어둔다.

일단 인터넷 검색을 하다보면 DataGridView1 라고 나온 것이 있는데, C#은 대문자, 소문자를 구분하기 때문에 dataGridView1 이라고 정확하게 적어줘야 에러가 발생하지 않는다.


엑셀 셀처럼 편집하는 기능으로 보이는데 기능을 제대로 파악하려면 아직 한참더 찾아보고 테스트를  해봐야할 거 같다.

자료의 내용은 개발 시험을 하면서 새롭게 알게된 것은 지속적으로 업데이트를 하고 있다.

마지막 업데이트 : 2015.9.7


//Fill grid with items
dataGridView1.DataSource = DS.Tables[0]; //바인딩부분


dataGridView1.RowHeadersVisible = false;  // 행 헤더 숨기기
//dataGridView1.BorderStyle = BorderStyle.Fixed3D;

dataGridView1.Columns[4].HeaderText = "가격";  // HeaderText(제목) 칼럼명 지정
dataGridView1.Columns[5].HeaderText = "수량";
//dataGridView1.Columns[6].Visible = false; // 화면에 보여주고 싶지 않은 칼럼 지정

// Header 가운데 맞춤
dataGridView1.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[1].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[2].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[3].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[4].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[5].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns[6].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
// 칼럼(열)의 수보다 많으면 Index 에러가 발생한다는 메시지를 보여줌


// 내용 가운데 맞춤
dataGridView1.Columns[1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.Columns["uid"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;


//dataGridView1.CurrentCell = null;
dataGridView1.AllowUserToOrderColumns = true;  // Column 별로 Sort 및 열 순서 변경 가능
// 열의 순서를 변경해도 MySQL 테이블에는 정상적으로 데이터가 저장됨
dataGridView1.Columns[1].SortMode = DataGridViewColumnSortMode.NotSortable; // Column 정렬(Sort) 못하게
dataGridView1.Columns[2].SortMode = DataGridViewColumnSortMode.NotSortable;

// Read Only Columns and Rows
//dataGridView1.ReadOnly = true;  // 모든 칼럼을 읽기 전용으로 만들기 때문에 특정 칼럼만 수정 불가
dataGridView1.Columns[2].ReadOnly = true; // 특정 칼럼 읽기 전용으로 적용하기
dataGridView1.Columns[3].ReadOnly = true;
dataGridView1.Columns[4].ReadOnly = true;
dataGridView1.Columns[6].ReadOnly = true;

dataGridView1.AllowUserToResizeColumns = false; // Header Column 너비 조정
//dataGridView1.Columns[1].Visible = false; // 칼럼(열) 숨기기
//dataGridView1.RowTemplate.Height = 35; // 셀 높이 결정


dataGridView1.AllowUserToAddRows = false;  // 빈레코드 표시 안하기

빈 여백없이 화면에 출력되도록 하려면

dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

dataGridView1.AutoResizeColumns();  // 각 열의 데이터에 맞게 자동으로 사이즈를 조절


// 칼럼 출력 자동 맞추기
dataGridView1.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
dataGridView1.Columns[4].DefaultCellStyle.Format = "###,##0";  // 숫자표시 칼럼


칼럼에 따라 너비를 고정으로 하고 싶은 경우가 있다.

dataGridView1.Columns[0].Width = 50;  // Header 너비 수동 설정

처럼 Column 너비만 고정으로 했더니 화면 해상도에 따라 자동으로 크기가 변한다.

칼럼 크기를 완전히 고정하려면

dataGridView1.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
dataGridView1.Columns[1].Width = 70;

이 두개를 같이 적어줘야 모니터 해상도와 관계없이 고정적으로 변하지 않는다.

칼럼명은 숫자보다 직접 칼럼명을 적어주는 것이 좋다.

dataGridView1.Columns["cate1"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;

dataGridView1.Columns["cate1"].Width = 70;

나머지 칼럼은 해상도에 따라 적정하게 채워주면 된다.

private void getScreenResolution()
{
     int screenWidth = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;
     int screenHeight = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;
}

private void setAutoSizeColumnsMode()
{
     if (screenWidth <= 1680 || screenHeight  <= 768)
         dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
     else
         dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}



// 그리드 셀 배경색 지정
//dataGridView1.Columns[0].DefaultCellStyle.BackColor = Color.FromArgb(240, 240, 240);
//dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.LightCyan;
dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;


private void btn_CellUpdate_Click(object sender, EventArgs e)
{
    // 선택한 셀의 타입 알아보기
    if (typeof(Int32) == dataGridView1.SelectedCells[0].Value.GetType())
    {
        MessageBox.Show("dataGridView1 Cell Value is 숫자");
    }
    else if (typeof(string) == dataGridView1.SelectedCells[0].Value.GetType())
    {
        MessageBox.Show("dataGridView1 Cell Value is 문자열 ");
    }
    else
    {
        MessageBox.Show(dataGridView1.SelectedCells[0].Value.GetType().ToString());
    }
}


마우스 오버 상태에서 highlight 표시 처리

int OldRow = 0;
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
    DataGridView.HitTestInfo hti = dataGridView1.HitTest(e.X, e.Y);

    if (hti.RowIndex >= 0 && hti.RowIndex != OldRow)
    {
        dataGridView1.Rows[OldRow].Selected = false;
        dataGridView1.Rows[hti.RowIndex].Selected = true;
        OldRow = hti.RowIndex;
    }
}

블로그 이미지

Link2Me

,
728x90

홀수행과 짝수행의 배경색을 다르게 지정하는 방법이 아래 코드 한줄이면 된다.

dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;



아래와 같은 코드도 한 행씩 건너뛰면서 배경색상을 다르게 준다.

for (int i = 1; i < dataGridView1.Rows.Count; i++)
{
       if (i % 2 != 0)
       {
              dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.FromArgb(240, 255, 240);
        }
        else
        {
             dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.White;
        }
}


위 코드에서 Rows 대신에 Columns 를 하면 칼럼(column)의 배경색을 변경할 수 있다.

블로그 이미지

Link2Me

,