본문 바로가기
프로그래밍/C#

[C#] 그리드뷰 엑셀 내보내기

by 코딩연습생 2020. 7. 24.
반응형

안녕하세요~

 

코딩연습생입니다

 

C# WINFORM에서 그리드뷰의 내용은 엑셀로 내보개기에 대한 포스팅을 할려고 합니다

 

예전 OLEDB를 이용한 엑셀 연동을 포스팅한적이 있는데요

 

 

https://codingman.tistory.com/103?category=715728

 

[C#] OLEDB를 통한 엑셀파일 불러오기(데이터그리드뷰)

안녕하세요 코딩 연습생 입니다 이전 포스팅에서 직접 엑셀의 API를 활용하여 엑셀파일의 내용을 불러와 데이터그리드뷰와 연동하는 포스팅을 업로드했었는데요 https://codingman.tistory.com/100 [C#] ��

codingman.tistory.com

 

해당 예제를 사용하여 구현하셔도 상관은 없습니다~ 하지만 이번엔 Interop.Excel를 사용하여 구현을 해볼껀데요

 

프로젝트를 하나 생성하시고 윈폼을 하나 만듭니다

 

 

저는 위와 같은 화면을 디자인해서 생성하였습니다

 

아래쪽에 보이는 그리드뷰 영역에 "엑셀"이라는 버튼을 누루면 내보내기가 가능한 기능을 구현을 해볼려고 해요

 

일단 첫번째로 엑셀을 사용하기 위한 선언을 합니다

using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;
using System.IO;

 

두번째는 버튼을 추가하여 클릭 이벤트를 생성한뒤에 다음과 같이 코딩을 합니다

 

        private void hoverGradientButton3_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = "Save as Excel File";
            sfd.Filter = "Excel Documents (*.xls)|*.xls";
            sfd.FileName = "납품처마스터.xls";

            if (sfd.ShowDialog() == DialogResult.OK)
            {
                copyAlltoClipboard();

                object misValue = System.Reflection.Missing.Value;
                Excel.Application xlexcel = new Excel.Application();

                xlexcel.DisplayAlerts = false;
                Excel.Workbook xlWorkBook = xlexcel.Workbooks.Add(misValue);
                Excel.Worksheet xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

                try
                {
                    Excel.Range rng = xlWorkSheet.get_Range("D:D").Cells;
                    rng.NumberFormat = "@";
                    Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1];
                    CR.Select();
                    xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true);

                    xlWorkBook.SaveAs(sfd.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
                    xlexcel.DisplayAlerts = true;
                    xlWorkBook.Close(true, misValue, misValue);

                    //파일 닫기... 
                    uint processId = 0;
                    GetWindowThreadProcessId(new IntPtr(xlexcel.Hwnd), out processId);
                    xlexcel.Quit();
                    if (processId != 0)
                    {
                        System.Diagnostics.Process excelProcess = System.Diagnostics.Process.GetProcessById((int)processId);
                        excelProcess.CloseMainWindow();
                        excelProcess.Refresh();
                        excelProcess.Kill();
                    }

                    MessageBox.Show("엑셀 파일 생성이 완료 되었습니다.");

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                    xlWorkBook.Close();
                    uint processId = 0;
                    GetWindowThreadProcessId(new IntPtr(xlexcel.Hwnd), out processId);
                    xlexcel.Quit();
                    if (processId != 0)
                    {
                        System.Diagnostics.Process excelProcess = System.Diagnostics.Process.GetProcessById((int)processId);
                        excelProcess.CloseMainWindow();
                        excelProcess.Refresh();
                        excelProcess.Kill();
                    }
                }
            }
        }

 

몇가지 오류가 뜨실껀데 아래의 내용을 적용하면 모두 해결 되실겁니다

 

두번째는 그리드뷰의 내용을 클립보드(Clipboard)안에 담는 함수 부분입니다

 

        private void copyAlltoClipboard()
        {
            dataGridView1.SelectAll();
            DataObject dataObj = dataGridView1.GetClipboardContent();
            if (dataObj != null)
                Clipboard.SetDataObject(dataObj);
        }

 

그리고 C#에서 엑셀을 연동하여 사용하시면 항상 프로세스에 엑셀 찌꺼기(?)가 남아 있습니다

 

그걸 해결하기 위해 몇번 삽질을 했는데요

 

이를 해결하기 위해 프로젝트 소스 상단에 DLL 하나를 Import 시켜줍니다

 

        [DllImport("user32.dll", SetLastError = true)]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

 

이렇게 하시면 엑셀 프로세스를 불러와 사용한뒤에 해당 PID값을 기억헀다가 종료시에 강제 삭제해주게 됩니다

 

 

실행 순서는 이렇게 됩니다

 

 

버튼을 누루게 되면

 

 

이렇게 저장 위치를 선택하실수 있게 나오고

 

 

저장이 완료되면 위의 사진과 같이 그리드가 전체 선택이 되면서 저장되어집니다

 

엑셀 파일을 열어보시면 이렇게 헤더까지 그대로 내보내기 되어 진 모습을 볼 수 있네요

 

 

감사합니다~

반응형

댓글