반응형

안녕하세요

 

코딩연습생입니다~

 

이전 포스팅에서 폴더안에 파일 내용을 보여주는 프로그램을 소개한적이 있는데요

 

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

 

[C#] 폴더안의 파일 목록 만들기(리스트박스)

안녕하세요 코딩연습생입니다~ 요즘 코로나도 문제이지만 태풍이 너무 많이 오네요~ 짜증날 정도로ㅎㅎ 글자님들도 코로나 + 태풍 조심하시길 바랍니다 이번 포스팅은 C#으로 리스트박스(ListBox)

codingman.tistory.com

이 프로그램을 조금 업그레이드시켜서 폴더안에 이미지 파일을 썸네일 형식으로 목록을 만들고 그 썸네일을 클릭하면

 

큰 이미지로 보기할 수 있는 뷰어(?) 프로그램을 만들어 볼려고 합니다

 

이전 화면에서 썸네일 이미지를 보여 주기 위해 조금 변경 했습니다

 

[화면 디자인]

 

파일 경로 안의 이미지 파일을 검색하여 이미지 갯수만 큼 panel을 생성하고 그 판넬안에 picturebox를 삽입하여

 

이미지를 삽입 시켜 주어서 썸네일을 만들고 해당 picturebox의 클릭이벤트를 생성하여 큰 picturebox에

 

이미지를 보여주는 그런 프로그램 입니다

 

코딩 순서 아래와 같이 정리 할 수 있습니다

 

▣ 기능 구현 순서

   1) 폴더 위치의 이미지 파일 검색

   2) 폴더안의 이미지 리스트를 배열로 생성

   3) 배열수 만큼의 판넬(Panel) 컨트롤 생성

   4) 판넬(Panel)안에 사진박스(PictureBox) 컨트롤 넣기

   5) 사진박스(PictureBox)에 이미지 보여주기

   6) 사진박스(PictureBox) 클릭 이벤트 생성

   7) 사진박스(PictureBox) 클릭시 확대 이미지 보여주기

 

▣ 소스코드

FolderBrowserDialog dialog = new FolderBrowserDialog(); 
if (dialog.ShowDialog() == DialogResult.OK) 
{ 
    string Folder_Path = dialog.SelectedPath; 
    DirectoryInfo di = new DirectoryInfo(Folder_Path); 
    if (di.Exists == true) 
    { 
    	string[] files = Directory.GetFiles(Folder_Path);
        imgList = files.Where(x => x.IndexOf(".jpg", StringComparison.OrdinalIgnoreCase) >= 0
                             || x.IndexOf(".png", StringComparison.OrdinalIgnoreCase) >= 0).Select(x => x).ToList();

        if (imgList.Count > 0)
        {
            tableLayoutPanel1.Visible = true;
            Image img = null;
            try
            {
               for (int i = 0; i < imgList.Count; i++)
               {
                   img = Image.FromFile(imgList[i]);

				   Panel pPanel = new Panel();
                   pPanel.BackColor = Color.Black;
                   pPanel.Size = new Size(150, 150);
                   pPanel.Padding = new System.Windows.Forms.Padding(4);

                   PictureBox pBox = new PictureBox();
                   pBox.BackColor = Color.DimGray;
                   pBox.Dock = DockStyle.Fill;
                   pBox.SizeMode = PictureBoxSizeMode.Zoom;
                   pBox.Image = img.GetThumbnailImage(150, 150, null, IntPtr.Zero);
                   pBox.Click += PBox_Click;
                   pBox.DoubleClick += PBox_DoubleClick;
                   pBox.Tag = i.ToString();
                   pPanel.Controls.Add(pBox);

                   this.uiFp_Image.Controls.Add(pPanel);
                 }
                }
               finally
               {
                   img.Dispose();
               }
           }
           else
           {
              tableLayoutPanel1.Visible = false;
           }

			if (imgList.Count > 0)
            {
                 Panel pnl = this.uiFp_Image.Controls[0] as Panel;
                 PictureBox pb = pnl.Controls[0] as PictureBox;
                 uiTxt_ImgFile.Text = this.imgList[0];
                 PBox_Click(pb, null);
            }
       }
   }

 

이렇게 코딩을 하시게 되면 기능 구현 중 1번~6번까지가 완성 됩니다

 

마지막 클릭 이벤트를 연결해 줘야 겠죠?

 

        public void PBox_Click(object sender, EventArgs e)
        {                        
            for (int i = 0; i < this.uiFp_Image.Controls.Count; i++)
            {
                if (this.uiFp_Image.Controls[i] is Panel)
                {
                    Panel pnl = this.uiFp_Image.Controls[i] as Panel;
                    pnl.BackColor = Color.Black;
                }
            }

            PictureBox pb = sender as PictureBox;
            pb.Parent.BackColor = Color.Red;

            int idx = Convert.ToInt32(pb.Tag.ToString());

            Image img = Image.FromFile(imgList[idx]);
            uiPb_Image.Image = img;
            uiPb_Image.SizeMode = PictureBoxSizeMode.StretchImage;
            uiTxt_ImgFile.Text = this.imgList[idx];
        }

 

위와 같이 코딩을 하시면 클릭한 사진박스(PictureBox)에 대한 이미지를 좌측의 썸네일 확대 이미지의

 

사진박스(PictureBox)로 이미지를 띄울수 있게 됩니다

 

반응형
반응형

안녕하세요

 

코딩연습생입니다~

 

이번 포스팅은 저번 포스팅에 이어서 C#으로 드라이브 용량을 표시하는 프로그램을 만들어 보겟습니다

 

저번 포스팅에서 기간별 폴더 자동 삭제 프로그램을 만들어 봤었는데 

 

현재 내 드라이브 용량이 얼마나 남았는지 확인하면 좋을거 같아서 이어서 포스팅하게 되엇습니다

 

이전 글을 확인하시고자 한다면 아래 링크를 통해 확인하시면 됩니다

 

https://codingman.tistory.com/122

 

[C#] 기간별 폴더 정리(삭제)하기

안녕하세요 코딩연습생입니다~ 이번 포스팅은 C# 언어로 기간별 폴더를 자동 관리하기 위한 삭제 프로그램을 만들어 볼려고 합니다 [준비과정] 1. Form1을 생성하여 기준일을 생성할 텍스트 박스��

codingman.tistory.com

[준비 과정]

1. 비쥬얼 스튜디오 기본 컨트롤러 필요

   - 포스그레스바(ProgressBar), 레이블(Lable), 버튼(Button)

2. 디자인 폼은 이전 포스팅에서 만든 것을 이용할 예정입니다

 

[디자인]

1. ProgressBar

2. Lable를 통한 명칭 표시 및 용량 표시

3. 버튼을 통한 조회

 

[코딩]

- 조회 버튼 클릭 이벤트 발생시 프로그레스바(ProgressBar)용량 표시 및 Lable 수치 값 표시

1. SetDriveSize 변수 생성

   - 프로그레스바(ProgressBar) 및 Lable 값 생성

        public void SetDriveSize(DriveInfo drive, ProgressBar pb, Label title, Label lb)
        {
            string driveName = string.Empty;
            string totalSize = string.Empty;
            string freeSize = string.Empty;
            string usage = string.Empty;

            try
            {
                driveName = drive.Name.Substring(0, 1).ToString();
                totalSize = Convert.ToInt32(drive.TotalSize / 1024 / 1024 / 1024).ToString();
                freeSize = Convert.ToInt32(drive.AvailableFreeSpace / 1024 / 1024 / 1024).ToString();
                usage = (Convert.ToInt32(totalSize) - Convert.ToInt32(freeSize)).ToString();

                pb.Maximum = Convert.ToInt32(totalSize);
                pb.Value = Convert.ToInt32(usage);

                title.Text = string.Format("Disk ({0}:)", driveName);
                title.AutoSize = true;

                lb.Text = string.Format("{0}GB of {1}GB available.", totalSize, freeSize);
                lb.AutoSize = true;
            }
            catch { }
        }

2. GetDrivesize 변수 생성

   - 조회 할려는 드라이브 찾기

        public void GetDriveSize()
        {
            DriveInfo[] drives = DriveInfo.GetDrives();

            foreach(DriveInfo drive in drives)
            {
                if(drive.DriveType == DriveType.Fixed)
                {
                    if(drive.Name.Contains("D"))
                    {
                        SetDriveSize(drive, progressBar1, label24, label25);
                    }
                }
            }
        }

 

3. 버튼 클릭 이벤트를 통한 호출

        private void customButton7_Click(object sender, EventArgs e)
        {
            if (One_Click())
            {
                GetDriveSize();
            }
        }

 

[실행 결과]

- 조회 버튼 클릭시 지정한 드라이브의 용량을 이렇게 표시 해줍니다

 

- 실제 드라이브 상태

반응형
반응형

안녕하세요

 

코딩연습생입니다~

 

이번 포스팅은 C# 언어로 기간별 폴더를 자동 관리하기 위한 삭제 프로그램을 만들어 볼려고 합니다

 

[준비과정]

1. Form1을 생성하여 기준일을 생성할 텍스트 박스를 생성.

2. 파일 삭제를 실행하기 위한 버튼.

 

[폴더 구조]

- 내문서 -> 대상 폴더(Origin, RESULT_OK, RESULT_NG_ -> 세부 하위 폴더들 존재 -> 일자별 폴더

  ex) C:\Users\Administrator\Documents\ImageLog\대상 폴더\하위 폴더

 

[디자인]

- 디자인은 꼭 똑같이 하실 필요는 없습니다~

- 대상위치는 대상 폴더를 지정하기 위한 콤보박스

- 폴더 List 세부 하위 폴더들을 리스트화 해주는 콤보박스

 

[코딩]

1. 대상 폴더를 지정한 뒤 조회 버튼을 눌러 세부 하위 폴더 리스트를 콤보박스화 시키는 부분

   - path 변수에 경로 변수는 사용하시는 환경에 다라 변경해주셔야 합니다

        private void Path_Combo()
        {
            if (comboBox1.SelectedIndex >= 0)
            {
                string path = textBox_path_to_pcl_vision.Text;
                path = System.IO.Path.Combine(path, "ImageLog");
                path = System.IO.Path.Combine(path, comboBox1.SelectedItem.ToString());

                DirectoryInfo di = new DirectoryInfo(path);
                if (di.Exists == true)
                {
                    DataTable dt = new DataTable();
                    dt.Columns.Add("FolderName", typeof(string));
                    dt.Columns.Add("FolderPath", typeof(string));

                    DataRow ds = null;

                    foreach (var file in di.GetDirectories())
                    {
                        ds = dt.NewRow();
                        ds["FolderName"] = file.Name;
                        ds["FolderPath"] = file.FullName;
                        dt.Rows.Add(ds);
                    }

                    comboBox2.DataSource = dt;
                    comboBox2.ValueMember = "FolderPath";
                    comboBox2.DisplayMember = "FolderName";
                }
            }
            else
            {
                MessageBox.Show("대상위치를 먼저 선택해주세요.");
            }
            
        }

 

- 대상 위치를 설정하고 조회버튼을 누루면 폴더 List 콤보박스에 하위 디렉토리 목록이 보이게 됩니다

*콤보박스에 ValueMember와 DisplayMember 사용 방법은 아래 링크를 통해 알아 보실 수 잇습니다

https://codingman.tistory.com/119

 

[C#] 폴더안의 파일 목록 만들기(리스트박스)

안녕하세요 코딩연습생입니다~ 요즘 코로나도 문제이지만 태풍이 너무 많이 오네요~ 짜증날 정도로ㅎㅎ 글자님들도 코로나 + 태풍 조심하시길 바랍니다 이번 포스팅은 C#으로 리스트박스(ListBox)

codingman.tistory.com

 

- 구동 시킨 모습입니다

 

- 이제 폴더 삭제를 하기 위한 정리 버튼을 하나 생성해주고 코딩을 해보겠습니다

 

- 정리 버튼 클릭 이벤트에 아래와 같이 코딩을 합니다

        public static void deleteFolder(string folderDir)
        {
            try
            {
                Form1 form = new Form1();

                //기본 일수 14일.
                int deleteday = 14;

                //일수를 수동 지정하였을 경우 해당 일수를 가져옴.
                if (form.FolderDay_Period.Text != "")
                {
                    deleteday = Convert.ToInt32(form.FolderDay_Period.Text);
                }
                
                DirectoryInfo di = new DirectoryInfo(folderDir);
                if (di.Exists)
                {
                    DirectoryInfo[] dirInfo = di.GetDirectories();
                    string IDate = DateTime.Today.AddDays(-deleteday).ToString("yyyyMMdd");

                    foreach (DirectoryInfo dir in dirInfo)
                    {
                        if (IDate.CompareTo(dir.LastWriteTime.ToString("yyyyMMdd")) > 0)
                        {
                            dir.Attributes = FileAttributes.Normal;
                            dir.Delete(true);
                        }
                    }
                }

            }
            catch (Exception) { }
        }

 

- 기준 일자를 설정한뒤 정리 버튼을 누루면 

   대상위치의 하위 폴더의 자식 폴더들 중 생성기간을 기준으로 이전 폴더를 삭제 합니다

 

[실행]

- 내문에서 Origin이라는 폴더에 Cam1_Model_1이라는 하위 폴더 내용을 구조는 아래와 같습니다

 

- 정리 버튼을 누루게 되면 수정한 날짜 지금 현재(2020-09-15)이기 때문에 모두 삭제가 되어야 합니다

  기준 일자 설정이 기본 14일로 지정되어 있기 때문에 별도 일자 설정을 하지 않았다면

  모두 삭제가 되는것이 정상이겠죠?

 

 

- 정상 동작하는걸 확인 했습니다

   이 루트를 반복 시행이나 타이머를 통해 자동 실행되도록 한다면 용량 부족 현상을 막을수 있습니다~

반응형
반응형

안녕하세요~

 

코딩연습생입니다 ㅎㅎ

 

 

이번 포스팅은 팁이라고 하기엔 좀 모호 할수 있는 내용입니다

 

머신러닝을 공부하면서 많이 접하게 되는 것이 바로 파이썬인데요

 

그중에서도 저는 파이토치(PyTorch)를 사용하여 딥러닝을 구현하고 있습니다

 

환경 구현을 C# + 파이썬 + MSSQL 이런 조합으로 구현을 하다가 C#에서 파이썬 py파일을 구동 시키는 법을

 

찾아 구현하게 되어 포스팅 합니다

 

첫번째로 경로 설정입니다

 

현재 PC의 설치된 파이썬 실행 파일을 환경변수에 잡아 주셔야 합니다

(Python.exe)

- 시스템 환경 변수

* 해당 환경 변수는 PC마다 상이할수 있으니 참고만 해주세요

 

 

그다음 C#에서 구동하고자 하는 py 파일의 경로를 지정해야 합니다

 

저는 경로를 클래스로 생성하여 프로젝트 시작 위치에서의 절대 경로를 변수로 지정했습니다

 

*경로는 환경 설정에 따라 다르니 참고만 해주세요

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data;

namespace PCL_Vision_Settings
{
    class Settings
    {
        public string STARTUP_PATH;
        public string PYTHON_ROOT_PATH;
        public string PYTHON_PATH;
        public string SERVER_PATH;
        public string TRAINING_PATH;
        public string OCR_PREPROCESSING_PATH;
        public string OCR_TRAINING_PATH;
        
        public Settings()
        {
        	STARTUP_PATH = System.Windows.Forms.Application.StartupPath;
            PYTHON_ROOT_PATH = STARTUP_PATH + "Python API폴더 경로";
            PYTHON_PATH = "python.exe 파일 경로";
            SERVER_PATH = PYTHON_ROOT_PATH + "API 서버 실행을 위한 스크립트 경로";
            TRAINING_PATH = PYTHON_ROOT_PATH + "분류 훈련을 위한 스크립트 경로";
            OCR_PREPROCESSING_PATH = PYTHON_ROOT_PATH + "OCR 전처리를 위한 스크립트 경로";
            OCR_TRAINING_PATH = PYTHON_ROOT_PATH + "OCR 주석 작업 및 훈련을 위한 스크립트 경로";
        }

 

위의 소스처럼 변수를 전역변수로 설정하여 클래스에서 절대경로를 설정해주었습니다

 

 

그다음 비쥬얼스튜디오(C#)의 메인 화면으로 돌아와서 버튼이나 py파일을 구동하고자 하는 위치에 다음과 같이

 

코딩을 합니다

 

            string python_path = "\"" + 파이썬 경로 확인 + "\"";
            string training_path = "\"" + 훈련 스크립트 파일 경로 확인 + "\"";
            term_message = 훈련 관련 정보를 추강 입력 인자로 전달;
            System.Diagnostics.Process.Start(python_path, term_message); // 훈련 실행

 

좀 어렵죠??

 

 

정리를 하자면 절대경로를 설정하여 

 

System.Diagnostics.Process.Start()

 

사용하여 py 파일을 python으로 실행시키는 겁니다

 

이러게 한뒤 실행을 하면

 

 

위의 그림처럼 python.exe가 실행되면서 설정해준 py파일을 불러와 자동 실행 시키게 됩니다

 

최대한 내용을 정리해서 포스팅을 했는데 이해가 잘 안되실수도 있습니다~

 

그럴때는 직접 한번 구현해보시면 쉽게 이해가 되실거라 생각됩니다^^

 

반응형
반응형

안녕하세요

 

코딩연습생입니다~

 

요즘 코로나도 문제이지만 태풍이 너무 많이 오네요~ 짜증날 정도로ㅎㅎ

글자님들도 코로나 + 태풍 조심하시길 바랍니다

 

이번 포스팅은 C#으로 리스트박스(ListBox)를 사용하여 폴더내의 파일 목록을 만들고 

 

ValueMember와 DisplayMember를 사용하여 속성값, 보여지기값을 사용하는 방법을 알려드릴려고 합니다

 

물론, 이미 다 아실수도 있지만 저는 머리가 나빠서 기록차원에서 포스팅 할께요~ㅎ

 

일단 첫번째는 버튼을 통해 폴더 지정하는 방법입니다

 

그럼 젤 중요한 버튼이 있어야죠

 

간단하게 저는 폴더라는 이름으로 버튼을 생성했습니다

 

그리고 버튼 Click 이벤트에 아래와 같이 코딩을 했습니다

 

                FolderBrowserDialog dialog = new FolderBrowserDialog();
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                
                }

 

폴더를 선택할 수 있는 Dialog를 띄우기 위함입니다

 

버튼을 누루면 아래와 같은 선택 창이 띄게 되지요

 

그럼 두번째로 폴더를 선택한뒤에 그 폴더안에 있는 하위 파일 목록을 만들어야 합니다

 

그 리스트는 C#의 기본 컨트롤중에 리스트박스(ListBox)를 사용했습니다

 

화면 디자인은 심플합니다

그다음 아까 만들었던 버튼 Click이벤트에 파일 목록을 가져와서 리스트뷰에 뿌려줄수 있게 코딩을 합니다

 

                FolderBrowserDialog dialog = new FolderBrowserDialog();
                if (dialog.ShowDialog() == DialogResult.OK)
                {

                    //불량 이미지 폴더
                    string Folder_Path = dialog.SelectedPath;

                    this.listBox1.Refresh();
                    
                    DirectoryInfo di = new DirectoryInfo(Folder_Path);

                    if (di.Exists == true)
                    {
                        DataTable dt = new DataTable();
                        dt.Columns.Add("FileName", typeof(string));
                        dt.Columns.Add("FullName", typeof(string));

                        DataRow ds = null;

                        foreach (FileInfo file in di.GetFiles())
                        {
                            ds = dt.NewRow();
                            ds["FileName"] = file.Name.Substring(0, file.Name.Length - 4);
                            ds["FullName"] = file.FullName;
                            dt.Rows.Add(ds);
                        }

                        listBox1.DataSource = dt;
                        listBox1.ValueMember = "FullName";
                        listBox1.DisplayMember = "FileName";
                        

                    }
                }

 

여기서 보셔야 할 부분은 DataTable를 생성하여 컬럼을 임의로 생성한 부분

 

                        DataTable dt = new DataTable();
                        dt.Columns.Add("FileName", typeof(string));
                        dt.Columns.Add("FullName", typeof(string));

 

그리고 리스트뷰(ListView)에 DataSource를 사용하여 DataTable값을 넣어주고 ValueMember와 DisplayMember를 

 

사용한 부분

 

                        listBox1.DataSource = dt;
                        listBox1.ValueMember = "FullName";
                        listBox1.DisplayMember = "FileName";

 

이렇게 사용하시게 되면 화면에 보이는 값과 속성 값을 따로 사용하실 수 있습니다

 

 

이렇게 활용하여 사용하실수 있습니다

 

반응형
반응형

안녕하세요

 

코딩연습생입니다~

 

아직 끝나지 않은 코로나로 인해 여간 힘든게 아니네요~

 

여러분들도 모두 코로나 감염으로 부터 조심하시길 바랍니다

 

이번 포스팅은 비쥬얼스튜디오(Microsoft Visual Studio)에서 기본으로 제공되고 있는 데이터그리드뷰(DataGridView)를

 

사용할때 기본 디자인이 너무 구리죠?ㅎㅎ

 

 

갠취이긴 하지만 저는 너무 구리게 느껴집니다 그래서 약간의 설정으로 그래도 조금 있어보이는(?) 그런 그리드뷰로 

 

변경할 수 있는 설정법을 알려드릴려고 합니다

 

비쥬얼스튜디오(Microsoft Visual Studio)를 많이 사용하신분들이면 누구나 알고 계시겠지만 저는 어디까지나

 

초보(?) 아니면 연습생(?) 이런 분들을 위한 포스팅이니 이미 알고 계신분들이라면 뒤로가기를 누루시기 바랍니다ㅎㅎ

 

간혹 이런거 포스팅 하지 말아라 라고 말씀하시는 분들고 계셔서 맘이 아플때가 있어서..ㅠ

 

 

[디자인]

1. C#의 Form에 비쥬얼스튜디오(Microsoft Visual Studio)에서 기본적으로 제공하는 데이터그리드뷰(DataGridView)를 삽입합니다

 

- 삽입하는 방법은 좌측 도구상자탭에서 모든 Windows Forms 항목 중에 DataGridView 컨트롤을 마우스로 드래그앤드롭하여 사입합니다

 

 

2. 삽입된 데이터그리드뷰(DataGridView)를 마우스로 클릭하여 속성창에서 아래와 같이 수정합니다

   - AllowUserToAddRows의 속성을 False로 변경

   - AllowUserToAddRows는 기본상태에서 Rows 한줄을 보여줄것인지 하는것 입니다

   - SelectionMode를 FullRowSelect로 변경

   - 데이터그리드뷰(DataGrideView)의 내용을 선택했을때 선택 방법을 설정합니다

     (사용 용도에 따라 사용하셔도 됩니다)

   - 다음 모양 속성 변경입니다 위에서 아래로 상세 설정 화면입니다

 

   - AlternatingRowsDefaultCell 속성

   - 데이터그리드뷰(DataGrideView)의 내용 부분을 별도 설정없이 Row의 구분 색상을 표현 해줍니다

      (말로 이해가 안되시는분은 제일 마지막 완성 이미지를 보시면 이해 하실겁니다)

 

   - ColumnHeadersDefaultCell 기본 헤더 디자인 변경

   - 헤더의 기본 색생, 정렬, 크기등을 설정합니다

 

   - ★ EnableHeadersVisualStyles 값을 False로 변경

         (해당 옵션을 변경하지 않으면 디자인을 변경하셔도 화면에 표시되지 않습니다)

 

이렇게 기본 데이터그리드뷰(DataGridView) 속성을 몇개를 바꾸고 적용하면 아래와 같이

 

멋있는(?) 그리드뷰로 변경됩니다~

 

 

 

앞서 말씀드렸듯이 어디까지나 갠취입니다;;ㅎㅎ 욕하지 마세요~

반응형
반응형

안녕하세요

 

코딩연습생입니다

 

비쥬얼스튜디오 2010에서 작성한 C#코드를 비쥬얼 스튜디오 2017이 설치되어 있는 PC로 복사 후 실행 하였더니..

 

난생 처음 보는 에러가 뜨네요

 

 

헉...핵 당황...

 

처음 보는 오류라서 구글 검색을 엄청 많이 해봤어요

 

 

모든 외국 싸이트의 헬퍼글까지 읽었지만...

 

해결 방법이 안나오더라구요

 

제가 해본 방법은

 

1. Nuget으로 "Microsoft.CodeDom.Providers.DotNetCompilerPlatform"의 최신버전을 설치 해봐라.

   - 결과 실패

   - 다시 복원하는게 짜증남

 

2. C:\Users\Administrator\AppData\Local\Temp 폴더안에 있는 어셈블리를 삭제후 리빌드해봐라

  - 해당 폴더에 가면 아래와 같은 파일이 있는데 이걸 삭제 해보라고 함

  - 결과 실패

 

3. 언어 버전을 변경해 봐라

  - C# 4.0이 비쥬얼 스튜디오 2010, 비쥬얼스튜디오 2017은 C# 6.0을 지원한다고 합니다

  - 결과 실패

 

4. 소스 코드 재 설정(?)

  - 구글 검색하다 해외 헬퍼 글에서 이상한 글을 보게 됨

  - 빨간줄을 친 부분 간략하게 해석을 하면 

    '문제가 생긴 오류 코드에서 보이지 않는 오류 부분을 포함한 3줄을 삭제 후에 Enter키를 한번 누루고 재작성하면

    해결 됩니다.."

    무슨 X소리야!!!!

 

하지만 쥐푸라기라도 잡고 싶은 심정으로 해봣습니다...

 

오류 화면 입니다 202 오류..

 

해외 글에서 있는것 처럼 3줄을 삭제 했습니다

 

오류 내용이 바뀌엇네요?? 왠지 뭐가 될거 같기도....

 

지웠던 3줄의 내용을 다시 타이핑해서 다시 재생성 헀습니다

 

 

어이 없게 오류가 싹 사라졌어요..

 

빌드를 해볼께요..

 

 

이런 어이 없는 결과가 나왓네요...해결 되었습니다

 

이유를 유추해보면 비쥬얼스튜디오 버전별 Bulider 버전이 상이한데 2010으로 작성된 소스코드를 강제로

 

복사하여 2017로 실행하엿을 경우 Bulider이가 소스 코드의 문자열 판독을 이상하게 한다(?)

 

그래서 복사된 2017에서 코드를 재생성해서 빌드를 해주면 올바른 버전에서 끝점을 인식하여 정상화 된다

 

이런 이유인거 같습니다

 

혹시 저와 같은 오류로 몇일째 시간을 허비 하시는 분들을 위해서 포스팅 올려 드리니 시간 허비 하지 마시고

 

해결 하세요~

 

반응형
반응형

안녕하세요~

 

코딩연습생입니다

 

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값을 기억헀다가 종료시에 강제 삭제해주게 됩니다

 

 

실행 순서는 이렇게 됩니다

 

 

버튼을 누루게 되면

 

 

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

 

 

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

 

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

 

 

감사합니다~

반응형

+ Recent posts