반응형

1. Point

  • 사전 준비 : '참조 - NuGet' 에서 NPOI를 설치
  • 엑셀 파일 생성
  • 워크 시트 생성
  •  

 

반응형

 

 

2. 전체 코드

// 참조 추가
using System.IO;
using NPOI.HSSF.Util;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;

namespace manual_NPOI_excel_IO
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var newFile = @"./dir/newbook.core.xlsx";

            using (var fs = new FileStream(newFile, FileMode.Create, FileAccess.Write))
            {
				// 워크북 생성
                IWorkbook workbook = new XSSFWorkbook();

                // 시트 생성
                ISheet sheet1 = workbook.CreateSheet("Sheet1");

                // 작업 내용 파일에 작성 및 저장
                workbook.Write(fs);
            }
        }
    }
}
반응형
반응형

1. 사용자가 많다

내가 라이브러리 선택하는 요소 중 가장 중요한 요소이다.

사용자가 많으면 그만큼 문제가 발생했을때 쉽게 검색과 대처가 가능하다.

 

 

 

반응형

 

2. 편의성

Microsoft.Office.Interop.Excel은 안정적이지 않았다.

가장 큰 문제는 파일 작성 후 excel 프로세스가 닫히지 않는 문제점

강제로 Marshal.ReleaseComObject()로 다 닫아줘야 하는데 코드가 길어지다보면 안되는 경우가 많이 발생한다.

또한 실행된 모든 excel을 종료하다보니 보고 있던 엑셀파일마저 닫혀버린다

그 상태로 다시 코드가 실행되면 또 다른 excel 프로세스가 실행된다.

 

NPOI는 경험상 아직 이런 문제는 발생하지 않았다.

많이 쓰는 오픈소스인데 이런 이슈가 없는것을 보면 없다고 봐도 무방할듯 하다.

반응형
반응형

1. Point

  • 폴더 / 파일 삭제하기 (delete)
  • 폴더 / 파일 복사 - 붙여넣기 (copy)
  • 폴더 / 파일 잘라내기 - 붙여넣기 (move)

 

반응형

 

 

2. 전체 코드

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

using System.IO;

namespace manual_file_MoveCopyDelete
{
    internal class Program
    {
        static void Main(string[] args)
        {
            DirectoryInfo s_path = new DirectoryInfo(@".\test_dir");
            DirectoryInfo t_path = new DirectoryInfo(@".\test_dir2");

            DirectoryInfo s_path2 = new DirectoryInfo(@".\test_dir3");
            DirectoryInfo t_path2 = new DirectoryInfo(@".\test_dir4");

			// 폴더 4개 생성
            s_path.Create();
            t_path.Create();
            s_path2.Create();
            t_path2.Create();

            // 파일 유무 확인
            // 'Directory.GetCurrentDirectory()' 현재 실행중인 프로그램의 위치 반환
            FileInfo file = new FileInfo(Directory.GetCurrentDirectory() + "/test_dir/test2.txt");
            if (!file.Exists)
            {
                FileStream fs = file.Create();
                fs.Close();
            }


            // 파일 복사
            // test_dir의 test2.txt를 t_path경로로 복사한다
            // true = 덮어쓰기 허용 여부
            // t_path 뒤의 이름을 변경하여 복사 하면서 파일 이름 변경도 한번에 가능하다.
            System.IO.File.Copy(s_path.ToString() + @"\test2.txt", t_path.ToString() + @"\test_copy.txt", true);
            System.IO.File.Copy(s_path.ToString() + @"\test2.txt", s_path2.ToString() + @"\test_copy.txt", true);

            // 파일 이동
            // t_path 뒤의 이름을 변경하여 복사 하면서 파일 이름 변경도 한번에 가능하다.

            System.IO.File.Move(s_path.ToString() + @"\test2.txt", t_path.ToString() + @"\test_move.txt");


            // 폴더 복사
            // test_dir3번 폴더가 test_dir4번 폴더 아래 dir폴더로 이름이 바뀌어 이동(move)
            System.IO.Directory.Move(s_path2.ToString(), t_path2.ToString() + @"/dir");

            // 폴더 삭제
            // true = 하위 폴더/파일 모두 삭제 여부
            System.IO.Directory.Delete(t_path2.ToString(), true);
        }
    }
}
반응형
반응형

1. Point

  • 텍스트 파일에 내용 쓰기
  • 내용 덮어쓰기
  • 내용 추가하기 (덛붙여쓰기)

 

 

반응형

 

 

2. 전체 코드

using System;

using System.IO;
using System.Diagnostics;

namespace manual_txt_IO
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 파일 경로
            FileInfo file = new FileInfo(Directory.GetCurrentDirectory() + "/test_dir2/test2.txt");


            // 파일 내용 저장
            FileStream fs2 = file.OpenWrite();
            TextWriter tw = new StreamWriter(fs2);

            // 파일 안에 있는 내용 지우고 아래 내용만 저장
            // tw가 선언된 뒤부터 추가한 내용들만 저장 (선언전에 있던 내용은 삭제)
            for (int i = 0; i < 100; i++)
            {
            	// 아래 내용이 100번 써진다
                tw.Write("\ntest1" + i);
            }
            // 꼭 Close()해줘야 다른 곳에서 파일 엑세스 에러가 발생하지 않는다
            tw.Close();
            fs2.Close();


            // 파일 내용 뒤에 추가하여 내용 저장
            // 따로 세이브 명령이 필요 없음
            //// 10만번 기준 8~9초 소요 (8300 ~ 9400 ms)
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < 100000; i++)
            {
                File.AppendAllText(Directory.GetCurrentDirectory() + "/test_dir2/test2.txt", "\ntest\n1234567890\n1234567890\n1234567890" + i);
            }
            string sw_time = sw.Elapsed.TotalMilliseconds.ToString();
            sw.Stop();
            Console.WriteLine(sw_time);

        }
    }
}
반응형
반응형

1. Point

  • 폴더 유무 확인 방법
  • 파일 유무 확인 방법

[C# 텍스트 파일]  01. 폴더/파일 유무 확인 방법

반응형

 

 

2. 전체 코드

using System;
using System.IO;

namespace manual_txt_IO
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 폴더 경로 설정
            DirectoryInfo d_info = new DirectoryInfo(@"./test_dir2");

            // 폴더 유무 확인
            if (!d_info.Exists)
            {
                // 폴더가 없는 경우 폴더 생성
                d_info.Create();
                // 폴더 전체경로(절대경로) 출력
                Console.WriteLine(d_info.FullName.ToString());
            }


            // 파일 유무 확인
            // 'Directory.GetCurrentDirectory()' 현재 실행중인 프로그램의 위치 반환
            FileInfo file = new FileInfo(Directory.GetCurrentDirectory() + "/test_dir2/test2.txt");
            if (!file.Exists)
            {
                FileStream fs = file.Create();
                fs.Close();
            }
        }
    }
}
반응형
반응형

1. 닷넷 스프레드 라이브러리 ReoGrid

  1) ReoGrid https://reogrid.net/  

 

ReoGrid - .NET Spreadsheet Component

Excel Compatibility Loading and saving Excel format, including style, format, drawings and charts. Learn More »

reogrid.net

 

 

 

2. 특징

  1) 무료다 (MIT License)

    (1) 상업용(기업용) 무료

    (2) 기타 상세 내용 링크 https://namu.wiki/w/MIT%20%ED%97%88%EA%B0%80%EC%84%9C

 

  2) 엑셀과 유사한 형태의 UI 컨트롤이다

    (1) 엑셀과 같은 워크 시트탭 기능

    (2) 각종 함수 사용이 가능

    (3) 디테일한 세팅이 가능

3. 단점

  1) 일부 기능 지원 문제

    (1) WPF에서 DropDownList기능 사용 불가

  2) 업데이트 문제

    (1) Github에서 이슈 토론은 이어지나 업데이트 소식은 없음 

반응형
반응형
  1. 프로젝트 목표
    1. 숫자 야구 게임 만들기
    2. MaskedTextBox를 이용하여 원하는 데이터만 받기
    3. 중복되지 않는 난수(Random) 만들기
  2. 프로젝트 내용 
    1. 게임 방법
      1. 게임 시작을 하면 플레이어가 알지 못하게 4자리의 난수를 생성(= 문제 숫자, qNum)
        1. 난수는 0~9로 각기 다른 숫자로 구성
      2. 플레이어는 9번의 기회동안 숫자를 입력하여 문제 숫자를 맞추면 승리
      3. 숫자와 위치 둘다 맞추면 1Strike, 숫자는 맞추되 위치를 틀리면 1ball
    2. 주요 사항
      1. 난수 4자리를 각기 다른 숫자로 구성할 것
        1. 각 자리의 중복 확인 구조를 넣을 것
      2. 입력받는 값은 4자리의 숫자일 것
        1. 윈폼의 MaskedTextBox를 이용하여 원하는 값만 받아 처리
  3. 전체 코드
    1. using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows.Forms;
      
      namespace Number_Baseball
      {
          public partial class Form1 : Form
          {
      
              public string qNum;
              public Boolean gameStartFlag;
              public int try_Count;
              int strikeCount = 0;
              int ballCount = 0;
              public Form1()
              {
                  InitializeComponent();
      
                  gameStartFlag = false;
      
              }
      
              private void btn_Start_Click(object sender, EventArgs e)
              {
                  //문제 숫자 만들기
                  Random rd = new Random();
                  string tempNum = "";
                  bool flag = true;
                  int cc = 0;
      
      
                  //문제 숫자4자리의 중복 제거
                  while(flag)
                  {
                      tempNum = "";
                      for(int k=0; k<4; k++)
                      {
                          tempNum += rd.Next(0, 10).ToString();
                      }
                      Console.WriteLine(tempNum);
                      cc = 0;
                      for (int i = 0; i < 4; i++)
                      {
                          for (int j = 0; j < 4; j++)
                          {
                              if (tempNum[i] == tempNum[j])
                              {
                                  cc += 1;
                              }
                          }
                      }
                      if(cc == 4)
                      {
                          flag = false;
                      }
      
                  }
                  qNum = tempNum;
      
      
                  gameStartFlag = true;
                  try_Count = 0;
      
                  //Try Label 초기화
                  label_Num1.Text = "----";
                  label_Num2.Text = "----";
                  label_Num3.Text = "----";
                  label_Num4.Text = "----";
                  label_Num5.Text = "----";
                  label_Num6.Text = "----";
                  label_Num7.Text = "----";
                  label_Num8.Text = "----";
                  label_Num9.Text = "----";
      
                  //Result Label 초기화
                  label_Result1.Text = "----";
                  label_Result2.Text = "----";
                  label_Result3.Text = "----";
                  label_Result4.Text = "----";
                  label_Result5.Text = "----";
                  label_Result6.Text = "----";
                  label_Result7.Text = "----";
                  label_Result8.Text = "----";
                  label_Result9.Text = "----";
      
                  //숫자 입력창 입력 제한 해제
                  maskedtxt_Try.ReadOnly = false;
                  //숫자 입력창 마스크 형식 설정(0은 정수만 가능한 자리수 표시)
                  maskedtxt_Try.Mask = "0000";
      
              }
      
              private void btn_Retire_Click(object sender, EventArgs e)
              {
                  qNum = "";
                  MessageBox.Show("Sorry about that...");
                  gameStartFlag = false;
              }
      
              private void btn_send_Click(object sender, EventArgs e)
              {
                  string tryNum;
                  tryNum = maskedtxt_Try.Text;
      
                  try_Count += 1;
                  string name = "label_Result" + try_Count.ToString();
                  Control ctnResult = this.Controls[name];
                  string name2 = "label_Num" + try_Count.ToString();
                  Control ctnNum = this.Controls[name2];
                  
                  strikeCount = 0;
                  ballCount = 0;
      
                  if (gameStartFlag == true)
                  {
                      if (maskedtxt_Try.MaskCompleted)
                      {
                          compareCheck(tryNum, qNum);
      
                          ctnNum.Text = tryNum;
                          ctnResult.Text = strikeCount + " S  " + ballCount + " B";
                      }
                      else
                      {
                          MessageBox.Show("Enter the number!");
                          try_Count -= 1;
                      }
                  }
                  else
                  {
                      MessageBox.Show("Please Press Start Button.");
                      Console.WriteLine("3");
                  }
      
                  maskedtxt_Try.Clear();
      
                  if(strikeCount == 4)
                  {
                      MessageBox.Show("You Win");
                  }
                  else if(try_Count == 9 && strikeCount != 4)
                  {
                      MessageBox.Show("You Lose");
                  }
              }
      
              public void compareCheck(string a, string b)
              {
                  for (int k = 0; k < 4; k++)
                  {
                      if (a[k] == b[k])
                      {
                          strikeCount += 1;
                      }
                  }
      
                  for (int i=0; i<4; i++)
                  {
                      for(int j=0; j<4; j++)
                      {
                          if(a[i] == b[j])
                          {
                              ballCount += 1;
                          }
                      }
                  }
                  ballCount -= strikeCount;
              }
          }
      }
  4. 윈폼 화면 구성
  5. Check Point
    1.  MaskedTextBox
      1. 일반적인 텍스트 박스(TextBox, RichTextBox등)과 다르게 프로그래머가 원하는 형식, 값만 사용자가 작성 가능하다.
      2. 위의 코드중 95번째줄을 보면 마스크 설정을 한 것을 알 수 있다.
        1. maskedtxt_try.Mask = "0000";
        2. 텍스트박스에 숫자4자리만 들어 갈 수 있도록 설정함 (0이 숫자를, 네개가 네자리를 뜻함)
        3. 관련 자료는 아래 MSDN에서 확인 가능
          1. https://docs.microsoft.com/ko-kr/dotnet/api/system.windows.forms.maskedtextbox.mask?view=net-5.0
    2. random 난수 만들기 (중복 없는 4자리수 만들기)
      1.            while(flag)
                    {
                        tempNum = "";
                        for(int k=0; k<4; k++)
                        {
                            tempNum += rd.Next(0, 10).ToString();
                        }
                        Console.WriteLine(tempNum);
                        cc = 0;
                        for (int i = 0; i < 4; i++)
                        {
                            for (int j = 0; j < 4; j++)
                            {
                                if (tempNum[i] == tempNum[j])
                                {
                                    cc += 1;
                                }
                            }
                        }
                        if(cc == 4)
                        {
                            flag = false;
                        }
                    }
  6. 다운로드
    1. Number_Baseball.exe
      0.01MB
    2. Number_Baseball.zip
      0.05MB
반응형
반응형

C#으로 엑셀 폰트 크기, 굵게, 이탤릭, 기울임, 밑줄, 취소선, 색상, 정렬 등 설정하기

 

1. 목표

  • 폰트를 설정한다.
  • 폰트 사이즈를 설정한다.
  • 폰트에 굵게, 기울임을 설정한다.
  • 폰트 색상을 설정한다.
  • 폰트를 좌우 정렬, 상하 정렬 한다.

 

2. 전체 코드

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

using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Drawing;

namespace chapter_07
{
    class Program
    {
        static void Main(string[] args)
        {
            Application excelapp = new Application();
            Workbook wb = excelapp.Workbooks.Add();
            Worksheet ws = wb.Worksheets.Item[1];

            Range rg = ws.Range[ws.Cells[1, 1], ws.Cells[5,5]];
            rg.Value = "123";

            rg.Font.Name = "맑은고딕";
            rg.Font.Size = 20;
            rg.Font.Bold = true;
            rg.Font.Italic = true;
            
            rg.Font.Underline = true;
            rg.Font.Strikethrough = true;            
            rg.Font.Color = Color.FromArgb(51, 102, 51);

            rg.HorizontalAlignment = 3;
            rg.VerticalAlignment = 2


            wb.SaveAs(Filename:@"C:\test\555.xlsx");
            wb.Close();
            excelapp.Quit();
            Marshal.ReleaseComObject(wb);
            Marshal.ReleaseComObject(rg);
            Marshal.ReleaseComObject(excelapp);
        }
    }
}

 

 

3. 뜯어 보기

rg.Font.Name = "맑은고딕";
rg.Font.Size = 20;
rg.Font.Bold = true;
rg.Font.Italic = true;
  • rg.Font.Name : 해당 범위의 폰트를 변경한다.

  • rg.Font.Size : 해당 범위의 폰트 사이즈를 변경한다.

  • rg.Font.Bold : 해당 범위 폰트를 굵게 쓸지 여부를 결정한다.

  • rg.Font.Italic : 해당 범위 폰트를 기울일지(이탤릭체) 여부를 결정한다.

rg.Font.Underline = true;
rg.Font.Strikethrough = true;
rg.Font.Color = Color.FromArgb(51, 102, 51);
  • rg.Font.Underline : 글자에 밑줄을 그을지 설정한다.

  • rg.Font.Strikethrough : 글자에 취소선을 그을지 설정한다. (예 : 가나다)

  • rg.Font.Color : 폰트의 색상을 설정한다.

    • 앞선 포스트에서 사용한 System.Drawing을 참조하여야 Color.FromArgb를 사용 가능하다.

    • FromArgb(red, green, blue) : 각가 원하는 RGB값을 넣어 색상을 설정한다.

rg.HorizontalAlignment = 3;
rg.VerticalAlignment = 2;
  • rg.HorizontalAlignment : 선택 범위의 좌우 정렬을 설정한다.

    • 값은 2, 3, 4를 넣을 수 있다

    • 2 : 왼쪽 정렬

    • 3 : 중앙 정렬

    • 4 : 오른쪽 정렬

  • rg.VerticalAlignment : 선택 범위의 상하 정렬을 설정한다.

    • 값은 1, 2, 3을 넣을 수 있다.

    • 1 : 상단 정렬

    • 2 : 중앙 정렬

    • 3 : 하단 정렬

반응형

+ Recent posts