728x90

지정된 타이머 간격이 경과되고 타이머를 사용할 수 있을 때 발생다.


도구상자에서 타이머를 끌어다 놓는다.


타이머를 선택하고 이벤트 아이콘을 클릭하여 Tick 이벤트를 더블 클릭한다.



this.timer1.Tick += new System.EventHandler(this.timer1_Tick); 다.

private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Enabled = false;
    listView_MyItem(listView1);  //
타이머에서 동작시킬 사용자 함수
}


위의 굵은 글씨 부분을 보면 User가 직접 작성하는 코드를 어떻게 추가하는지를 알 수 있다.

마우스 휠 이벤트는 제공하지 않는데 마우스 휠 이벤트를 추가하는 방법은

this.listView1.MouseWheel += new MouseEventHandler(this.listView_MouseWheel); // 마우스 휠 이벤트

private void listView_MouseWheel(object sender, MouseEventArgs e)
{
    listView_MyItem(listView1);  // 사용자 함수
    timer1.Enabled = true;
}


리턴타입은 void, 두개의 argument를 받는 데, 첫번째 인자는 object 타입, 두번째 인자는 EventArgs의  자식클래스이다.


필요에 따라 timer1.Interval = 5000; // 5초 단위

로 설정하면 된다. bool flag 와 같이 코딩할 수도 있다.


Designer.cs 파일에서 timer 찾기로 찾아보니

this.timer1 = new System.Windows.Forms.Timer(this.components);

this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

private System.Windows.Forms.Timer timer1;

이 3줄이 추가되어 있다.


다른 걸 좀 더 찾아보니

this.listView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseClick);

이렇게 추가되어 있다. 마우스 휠 이벤트도 정확하게는

this.listView1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.listView_MouseWheel); 로 적어주는게 맞는가 보다.


http://www.csharpstudy.com/CSharp/CSharp-event.aspx 에 보면 이벤트 핸들러 설명이 잘 되어 있다.



제공하는 이벤트가 아니라 직접 타이머를 만들어서 사용할 때를 알아보자.

System.Windows.Forms.Timer mytimer = new System.Windows.Forms.Timer();

는 전역변수 선언공간에 선언한다.



mytimer.Interval = 100;

mytimer.Tick += new EventHandler(timer_tick);

mytimer.Start();


void timer_tick(object sender, System.EventArgs e)
{
      수행할 작업
      mytimer.Stop();
}


다.








블로그 이미지

Link2Me

,
728x90

자막에 나오는 시간 단위를 받아서 보기 좋게 정렬하는 코드이다.


public double TimeCodeValue(string timecode)
{
    // 00:01:53,039
    string[] parts = timecode.Replace(",", ":").Split(':', ',');
    double Hours = int.Parse(parts[0]);
    double Minutes = int.Parse(parts[1]);
    double Seconds = int.Parse(parts[2]);
    double Milliseconds = int.Parse(parts[3]);

    return (Hours * 3600 + Minutes * 60 + Seconds) * 1000 + Milliseconds;
}

public string TimeCodeFormat(double timecodevalue)
{

    // 91469

    double temptime = System.Math.Truncate(timecodevalue / 1000); // 몫
    double hour = System.Math.Truncate(temptime / 3600);
    double minute = System.Math.Truncate(temptime % 3600 / 60);
    double seconds = temptime % 3600 % 60;
    double milliseconds = timecodevalue % 1000; // 나머지
    return string.Format("{0:0}:{1:00}:{2:00},{3:000}", hour, minute, seconds, milliseconds);
}


1. 밀컨즈(milliseconds) 출하고
2. 시간 단위로 환산하기 위해서 3600(60분 X 60초)로 나눈 몫을 구한다.

    Math.Truncate 함수를 사용하여 반올림하지 않고 정수만 잘라낸다.

3. 분 단위로 환산하기 위해서

    시간단위로 나눈 나머지를 가지고 다수 몫을 구한다.

4. 초 를 구하기 위해서는

    시간단위, 분단위를 구한 나머지를 구한다.

5. 밀리세컨즈(milliseconds) 는 초단위로 환산하는 나머지를 구하면 된다.







'C# > 문법 및 기능' 카테고리의 다른 글

C# URL 경로 링크  (0) 2015.11.10
C# Timer.Tick 이벤트, 이벤트 분석  (0) 2015.10.22
C# 몫과 나머지 구하기  (0) 2015.10.17
C# 문자열 다루기 StringBuilder  (2) 2015.10.10
C# 문자열 분리 Split  (0) 2015.10.09
블로그 이미지

Link2Me

,
728x90

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

자동 설정하는 옵션은

dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;


수동 지정 방법은


Font Size 변경



블로그 이미지

Link2Me

,
728x90

C# 에서 몫(quotient) 과 나머지(remainder) 구해보자.


double a = 60;
double b = 23;
double c = a / b;
double quotient = System.Math.Truncate(c); // 몫
double remainder = a % b;  // 나머지
MessageBox.Show(c.ToString() + " 몫 : " + quotient.ToString() + " 나머지 : " + remainder.ToString());



몫을 구할 때 이렇게 안해주면 반올림 처리하여 3으로 표시될 수 있다는 점에 주의해야 한다.


블로그 이미지

Link2Me

,
728x90

listView 에서 행단위로 데이터를 삭제하고자 할 경우, Drag & Drop 으로 파일을 읽어들일 경우, 칼럼 하나를 보이지 않게 처리하고 싶은 경우의 코드이다.



private void cmLV1_Delete_Click(object sender, EventArgs e)
{
    DialogResult comfirm = MessageBox.Show("정말로 삭제하시겠습니까?", "데이터삭제", MessageBoxButtons.YesNo);
    switch (comfirm)
    {
        case DialogResult.Yes:
            DeleteLine_listView(listView1); // Line 삭제
            break;
        case DialogResult.No:
            break;
    }
}

private void listView1_DragDrop(object sender, DragEventArgs e)
{
     string[] files = (string[])e.Data.GetData(DataFormats.FileDrop, false);
     if (files.Length == 1)  // 파일 1개만 추가
     {
         string fileName = files[0];
         OpenSubtitle(fileName, listView1);
     }
 }

private void listView1_DragEnter(object sender, DragEventArgs e)
{
     if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
         e.Effect = DragDropEffects.All;
}


** 파일을 다중으로 선택하여 추가할 경우

private void listView1_DragDrop(object sender, DragEventArgs e)
{
    string[] filenames = (string[])e.Data.GetData(DataFormats.FileDrop, false);
    foreach (string filename in filenames)
    {
        try
        {
            Load_MP3(filename, listView1);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}


특정한 칼럼을 숨기고 싶을 때에는 너비를 0 으로 놓고 안보이게 하는 방법이 있다.

listView1.Columns[5].Width = 0;  // 6번째 칼럼을 숨기기 처리


// listView 헤더행 숨기기

listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;

블로그 이미지

Link2Me

,

C# Get Mac Address

C#/기능 활용 2015. 10. 12. 00:00
728x90

내 컴퓨터의 LAN 카드 MAC(하드웨어)주소를 알아내는 코드다.

MAC주소 포멧부분은 코드를 손을 봤다.

StringBuilder 기능을 활용하면 코드가 심플해진다.


private void GetMac_Click(object sender, EventArgs e)
{
    // MAC주소 가져오기
    MessageBox.Show(MACformat(GetMacAddress()));
}

public static string GetMacAddress()
{
    // MAC주소 가져오기
    return NetworkInterface.GetAllNetworkInterfaces()[0].GetPhysicalAddress().ToString();
}

public static string MACformat(string str)
{   //Mac주소 포맷
    StringBuilder sb = new StringBuilder();
    char[] chrArr = str.ToCharArray();
    for (int i = 0; i < chrArr.Length; i++)
    {
        int n = i + 1;
        if (sb.Length > 0 && n % 2 !=0) sb.Append("-");
        sb.Append(chrArr[i].ToString());
    }
    string mac = sb.ToString();
    return mac;
}


'C# > 기능 활용' 카테고리의 다른 글

C# DLL 만들기  (0) 2015.11.14
C# 프로그램 사용기한 체크  (0) 2015.10.23
C# Get IP Address (사설 IP, 공인 IP)  (0) 2015.10.11
C# 인코딩  (0) 2015.09.24
문자열 암호화 - RSA, MD5, DES  (0) 2015.08.07
블로그 이미지

Link2Me

,
728x90

내가 사용하는 IP주소를 알아내기 위한 코드이다.

단순하게 IP주소를 알아내는 코드를 사용하면 사설IP주소(공유기 또는 방화벽내에서 사설 IP)를 사용하는 곳에서는 실제 인터넷에 접속된 IP주소와 다를 수가 있다.

공인 IP주소를 확인하기 위해서 파싱 방식으로 처리하였다.


using System.Net;
using System.IO;
using System.Text.RegularExpressions;


private void button1_Click(object sender, EventArgs e)
{
    if (GetRealIP().Equals(GetFirstIPv4()))
    {
        MessageBox.Show("Your IP Address : " + GetRealIP());
    }
    else   //
    {
        MessageBox.Show("Your Public IP Address : " + GetRealIP() + Environment.NewLine + "Your Private IP Address : " + GetFirstIPv4());
    }
}

public static string GetRealIP()
{
    string url = "http://checkip.dyndns.org";  //
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "GET";

    string resResult = string.Empty;
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        StreamReader readerPost = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8, true);
        resResult = readerPost.ReadToEnd();
    }
    //MessageBox.Show(resResult);  //
    string realip = Parsing(Parsing(resResult, "Current IP Address:")[1], "</body>")[0].Trim();
    //MessageBox.Show(temp);  // 파싱한 이후의 메시지 확인
    return realip;
}

public static string[] Parsing(string _body, string _parseString)
{
    // 엑셀 VBA 에서 사용하는 Split 함수처럼 파싱을 쉽게 사용 가능하게 해줌
    // 만든이 : http://blog.naver.com/bobojisu
    return System.Text.RegularExpressions.Regex.Split(_body, _parseString);
}

public string GetFirstIPv4()
{
    Regex regex = new Regex(@"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$");
    foreach (System.Net.IPAddress ip in System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList)
    {
        if (regex.IsMatch(ip.ToString()))
        {
            return ip.ToString();
        }
    }
    return null;
}


공인(Public) IP 주소 가져오는 속도가 느려서 다른 사이트를 참조해서 작업을 했더니 Parinsing 함수쪽에서 에러가 발생한다. 그래서 다른 방법으로 해결을 했다.


public static string GetRealIP()
{
    string url = "http://www.findip.kr/";
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "GET";

    string resResult = string.Empty;
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        StreamReader readerPost = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8, true);
        resResult = readerPost.ReadToEnd();
    }

    if (resResult.IndexOf("내 아이피 주소(My IP Address) :") > 0)
    {
        int ingNO = resResult.IndexOf("내 아이피 주소(My IP Address) :");
        string varTemp = resResult.Substring(ingNO, 50);
        string realip = Parsing(Parsing(varTemp, "내 아이피 주소(My IP Address) :", 1), "</h1>", 0).Trim();
        return realip;
    }
    return null;
}

public static string Parsing(string _body, string _parseString, int no)
{
    // 엑셀 VBA 에서 사용하는 Split 함수
    string varTemp = _body.Split(new string[] { _parseString }, StringSplitOptions.None)[no];
    return varTemp;
}





'C# > 기능 활용' 카테고리의 다른 글

C# 프로그램 사용기한 체크  (0) 2015.10.23
C# Get Mac Address  (0) 2015.10.12
C# 인코딩  (0) 2015.09.24
문자열 암호화 - RSA, MD5, DES  (0) 2015.08.07
C# OS 버전 및 플랫폼 확인 방법  (0) 2015.08.06
블로그 이미지

Link2Me

,
728x90

public int IndexOf(string value);

// 문장내에서 특정 문자나 문자열이 맨 처음 발견되는 인덱스 번호를 알려주는 메서드

public string Replace(string oldValue, string newValue);

// 원래 문자/문자열을 대체할 문자/문자열로 변경

public string Substring(int startindex, int lenght);

// 시작위치 길이만큼 결과를 돌려줌, 는 0

다.



string delimiter = ",";  // 구분자
string _Header = string.Empty;
for (int i = 0; i < dgv.Columns.Count; i++)
{
    string strr = dgv.Columns[i].HeaderText;
    _Header += strr + delimiter;
}
_Header = _Header.Substring(0, _Header.Length - 1);  // 막 1
_Header = _Header.Trim();
MessageBox.Show(_Header);



System.Text.StringBuilder 클래스는 문자열을 버퍼형식으로 수정할 수 있도록 도와주는 클래스로 문자열을 추가, 수정, 삭제, 검색 등의 기능을 제공한다.


Append : 현재 StringBuilder 의 끝에 정보를 추가
Insert : 문자열/개체를 StringBuilder에서 지정한 인덱스 위치에 삽입
Remove : 현재 StringBuilder 에서 지정한 수만큼의 문자를 제거
Replace : 지정된 인덱스에 있는 문자를 대체
CopyTo : 현재 StringBuilder 특정위치에서 시작하여 바이트수만큼 목적지 문자배열의 특정위치에 복사할 때 사용
ToString : StringBuilder 의 값을 문자열로 변환


문자열을 합쳐나갈 때 StringBuilder 를 사용하면 처리속도가 훨씬 빠르다.

위에서 구분자(delimiter)를 주고 문자열을 합치고, 다시 Substring 으로 잘라내는 것보다 코드도 깔끔하고 성능도 우수하다.

StringBuilder sb = new StringBuilder();
for (int i = 0; i < dgv.Columns.Count; i++)
{
    if (sb.Length > 0)  // 최초에는 sb 길이가 0 이므로 , 가 추가되지 않는다.
    {
        sb.Append(",");
    }
    sb.Append(dgv.Columns[i].HeaderText);
    MessageBox.Show(sb.ToString()); // for 문을 돌면서 sb문자열의 결과를 확인
}


sb.Append(dgv.Columns[i].HeaderText); 대신에 sb.Append("'" + dgv.Columns[i].HeaderText + "'"); 를 하면 작은 따옴표로 값을 감싸면서 문자열을 얻어낼 수 있다.




블로그 이미지

Link2Me

,
728x90

C# Split함수의 경우 직접 문자열을 구분자로 줄수 없다.

Split 은 기본적으로 문자를 입력 받도록 되어 있다. 문자열을 char[]형식으로 변경 후 사용 가능하다.


string str = "서울시/서초구/양재동";
string[] result = str.Split(new char[] { '/' });  // /열 result 라.
for (int i = 0; i < result.Length ; i++)  // 은 0 며,
{
    MessageBox.Show(i + "번째 배열 ==> " + result[i]);
}


string str = "jsk005@naver.com";
char[] sp ="@".ToCharArray();
string[] result = str.Split(sp);
for (int i = 0; i < result.Length; i++)
{
    MessageBox.Show(i + "번째 배열 ==> " + result[i]);
}


string str = "홍 길 동";
string[] result = str.Split(new char[] {' '});  // new char[] {} 도 공백으로 나눈다는 의미
for (int i = 0; i < result.Length; i++)
{
    MessageBox.Show(i + "번째 배열 ==> " + result[i]);
}


위의 예제와 아래 예제의 차이점을 보면 split 자(char)열(string)이다.

string 으로 할 경우에는 반드시 StringSplitOptions.None 또는 StringSplitOptions.RemoveEmptyEntries 까지 추가해줘야만 에러가 발생하지 않는다. 물론 위의 것도 StringSplitOptions 를 추가해줘도 된다.


string str = "홍길동~~~이순신~~~강감찬~~~을지문덕";
string[] result = str.Split(new string[] {"~~~"}, StringSplitOptions.None);
for (int i = 0; i < result.Length; i++)
{
    MessageBox.Show(i + "번째 배열 ==> " + result[i]);
}

string[] separator = new string[1] { "\r\n\r\n" };  //분리할 기준 문자열
string[] strResult = s.Split(separator, StringSplitOptions.RemoveEmptyEntries);

  

* StringSplitOptions.None  //

* StringSplitOptions.RemoveEmptyEntries  // 반환값에 빈 부분 문자열 포함 안됨


foreach (string strValue in strResult)
{
   
}

또는

for (var i =0 ; i < strResult.Length ; i++)

{

}


//구

string str = "[stop]ONE[stop][stop]TWO[stop][stop][stop]THREE[stop][stop]";
string[] stringSeparators = new string[] { "[stop]" };
string[] result = str.Split(stringSeparators, StringSplitOptions.None);

for (int i = 0; i < result.Length; i++)
{
    if (String.IsNullOrEmpty(result[i]))  // null
    {
        MessageBox.Show("null" + result[i]);
    }
    else
    {
        MessageBox.Show(i + "번째 배열 ==> " + result[i]);
    }               
}


아래와 같이StringSplitOptions.RemoveEmptyEntries 으로 수정하면 결과가 어떻게 나올까?

string str = "[stop]ONE[stop][stop]TWO[stop][stop][stop]THREE[stop][stop]";
string[] stringSeparators = new string[] { "[stop]" };
string[] result = str.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); 

// 반환값에 빈 부분 문자열 포함 안됨
for (int i = 0; i < result.Length; i++)
{
    if (String.IsNullOrEmpty(result[i]))
    {
        MessageBox.Show("null" + result[i]);
    }
    else
    {
        MessageBox.Show(i + "번째 배열 ==> " + result[i]);
    }               
}

결과는 null 이나 공백은 무시되므로 배열은 0, 1, 2 만 추출된다.




System.Text.RegularExpressions.Regex.Split(자를 문자열, 정규식 문자열)

using System;
using System.Text.RegularExpressions;


string str = "cat\r\ndog\r\nanimal\r\nperson";
string[] result = Regex.Split(str, "\r\n");
for (int i = 0; i < result.Length; i++)
{
    MessageBox.Show(i + "번째 배열 ==> " + result[i]);
}



포함된 문자열의 개수 구하기
int
count = source.Split('/').Length - 1;


블로그 이미지

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

Visual Studio 에서 Line 번호를 보이게 하는 방법이다.





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

비주얼 스튜디오 2015 빌드 경로 변경 및 프로젝트 종속성  (0) 2016.01.04
.NET 4.0 설치 프로그램  (1) 2015.10.25
C# 메인폼 변경하는 방법  (0) 2015.09.15
C# statusStrip 메뉴  (2) 2015.09.10
What's New in C# 6.0  (0) 2015.09.05
블로그 이미지

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# 에서 칼럼의 첫번째에 체크박스를 그리는 방법이다.



먼저 listView 열편집(ColumnHeader 컬렉션 편집기)을 아래와 같이 첫번째 칼럼에는 텍스트는 빈공백으로 준다.열너비는 30이나 25 정도로 주면 된다.

소스코드에 직접 적어주려면 listView1.Columns[0].Width = 25;



DB에서 가져온 정보를 listView 화면에 출력할 때 아래와 같이 처리를 해준다.

listView1.Items.Clear();
if (R.HasRows)
{
    int i = 0;
    while (R.Read())
    {
        i = i + 1;
        ListViewItem lvt = new ListViewItem();
        //lvt.Text = i.ToString();  // 첫번째 열은 값을 넣지 않는다. checkbox 용도
        lvt.SubItems.Add(i.ToString());
        lvt.SubItems.Add(R["uid"].ToString());
        lvt.SubItems.Add(R.GetString(1));
        lvt.SubItems.Add(R.GetString(2));
        lvt.SubItems.Add(R.GetString(3));
        lvt.SubItems.Add(R.GetString(4));
        listView1.Items.Add(lvt);
    }
    lvt1totalcnt.Text = "총 " + i.ToString() + " Row";
}


다.

참고한 사이트

http://stackoverflow.com/questions/1778600/listview-header-check-box

http://egloos.zum.com/seraph4021/v/4798702


listView_Table 정보를 출력하는 함수에

listView1.CheckBoxes = true;
listview.OwnerDraw = true;

다.


또는 속성창에서 아래처럼 추가를 해준다.




Event를 추가한다.



이제 코드를 추가해준다.

private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
    if ((e.ColumnIndex == 0))
    {
        CheckBox cck = new CheckBox();
        Text = "";       
        listView1.SuspendLayout();  // 컨트롤의 레이아웃 논리를 임시로 일시 중단
        e.DrawBackground();  // 열 머리글의 배경색을 그리기
        cck.BackColor = Color.Transparent;
        cck.UseVisualStyleBackColor = true;  // 비주얼 스타일을 사용하여 배경을 그리면 true

        // 컨트롤의 범위를 지정된 위치와 크기로 설정 (Left x, Top y, width, height)
        cck.SetBounds(e.Bounds.X, e.Bounds.Y, cck.GetPreferredSize(new Size(e.Bounds.Width, e.Bounds.Height)).Width, cck.GetPreferredSize(new Size(e.Bounds.Width, e.Bounds.Height)).Width);

       // 컨트롤의 높이와 너비를 가져오거나 설정

        cck.Size = new Size((cck.GetPreferredSize(new Size((e.Bounds.Width - 1), e.Bounds.Height)).Width + 1), e.Bounds.Height);
        cck.Location = new Point(4, 0); // 왼쪽 위를 기준으로 컨트롤의 왼쪽 위의 좌표를 가져오거나 설정
        listView1.Controls.Add(cck);
        cck.Show();
        //cck.BringToFront();
       
Visible = true;  // 컨트롤과 모든 해당 자식 컨트롤이 표시되면 true

        e.DrawText((TextFormatFlags.VerticalCenter | TextFormatFlags.Left));
        cck.Click += new EventHandler(Bink);  // 컨트롤을 클릭하면 발생
        listView1.ResumeLayout(true);  // 일반 레이아웃 논리를 다시 시작

    }
    else
    {
        e.DrawDefault = true;
    }
}

// 컬럼헤더에 있는 체크박스 클릭시 나머지 체크박스들도 자동 체크되도록 하는 로직
private void Bink(object sender, System.EventArgs e)
{
    CheckBox cck = sender as CheckBox;
    for (int i = 0; i < listView1.Items.Count; i++)
    {
        listView1.Items[i].Checked = cck.Checked;
    }
}

private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
    e.DrawDefault = true;
}       

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    e.DrawDefault = true;
}


이렇게 하면 체크박스는 추가가 된다.

private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
로직에 문제가 있는지 몰라도 두개의 행을 선택하려고 Shift 또는 Ctrl 키를 누르면 화면이 이상해진다.
테스트 해보니까 이 부분 처리가 완벽하지 않는가 보다.


cck.BringToFront(); 부분을 주석처리하니까 이런 현상이 없어졌다.

다.


// 체크박스가 선택되어 있으면 삭제되는 함수

private void DeleteLineChecked_listView(ListView LV)
{
    for (int row = LV.Items.Count - 1; row >= 0; row--)
    {
        if (LV.Items[row].Checked)
        {
            //LV.Items.Remove(LV.Items[row]);
            LV.Items.RemoveAt(row);
        }
    }
    listView_No(LV);  // 번호 다시 매기기
}


listView1.CheckedItems.Count

while (LV.CheckedItems.Count > 0)
{
    ListViewItem row = LV.CheckedItems[0]; // 체크된 것 하나씩 지우면 첫번째 것이 된다
    LV.Items.Remove(row);
}


체크된 Line 을 다른 listView 로 복사하는 방법

private void CheckedLineCopyTo_listView(ListView LV1, ListView LV2)
{
    for (int row = LV1.Items.Count - 1; row >= 0; row--)  // 총 Line
    {
        if (LV1.Items[row].Checked)  //
        {
            LV2.Items[row].SubItems[3].Text = LV1.Items[row].SubItems[3].Text;  // listView1 서 listView2
        }
    }
    LV2.Update();  // listView2
}



블로그 이미지

Link2Me

,
728x90

listView 에서 행을 병합할 때 사용하는 코드입니다. 이 코드는 특정한 셀기준으로 병합처리를 했다. 여러행을 같이 처리하라면 더 추가해야 한다. 개념적인 것만 알아두면 응용은 할 수 있다.


private void LineMerge(ListView LV)
{
    // 첫번째 row 에 데이터 같이 저장, 두번째이후 row 삭제처리
    if (LV.SelectedIndices.Count >= 2)
    {
        for (int i = 0; i < LV.SelectedIndices.Count; i++)
        {
            string str = LV.SelectedItems[i].SubItems[2].Text;
            merge_str += str + System.Environment.NewLine; // 줄바꿈문자
        }
        LV.SelectedItems[0].SubItems[2].Text = merge_str.Trim();
        // MessageBox.Show(merge_str);  //
        merge_str = string.Empty;
        for (int i = LV.SelectedIndices.Count - 1; i > 0; i--)
        {
            LV.Items.Remove(LV.SelectedItems[i]); // 삭제는 index 번호가 큰번호에서 작은번호 순으로
        }
        listView_No(LV);  // renumbering
    }
    else
    {
        MessageBox.Show("최소 2개의 행을 선택해야 합니다");
        return;
    }
}


2. 선택된 Line 의 바로 이전행과 병합할 때

키포인트는 선택된 행의 index 를 구한 다음에 이전 행의 index 를 구해서
LV.Items[i].SubItems[3].Text // i = selectedindex
즉 LV.SelectedItems[0].SubItems[3].Text 가 아니라는 점이다.

private void LineMergeWithLineBefore(ListView LV)
{
    string delimiter = System.Environment.NewLine;
    if (LV.SelectedIndices.Count > 0)
    {
        int selectedindex = LV.SelectedItems[0].Index;
        int previousindex = selectedindex - 1;
        merge_str = LV.Items[previousindex].SubItems[3].Text + delimiter + LV.Items[selectedindex].SubItems[3].Text;
        LV.Items[previousindex].SubItems[3].Text = merge_str.Trim();
        LV.Items.Remove(LV.Items[selectedindex]);

        listView_No(LV);
    }
}


3. 선택된 Line 의 바로 다음행과 병합할 때

private void LineMergeWithLineAfter(ListView LV)
{
    string delimiter = System.Environment.NewLine;
    if (LV.SelectedIndices.Count > 0)
    {
        int selectedindex = LV.SelectedItems[0].Index;
        int nextindex = selectedindex + 1;
        merge_str = LV.Items[selectedindex].SubItems[3].Text + delimiter + LV.Items[nextindex].SubItems[3].Text;
        LV.Items[selectedindex].SubItems[3].Text = merge_str.Trim();
        LV.Items.Remove(LV.Items[nextindex]);

        listView_No(LV);
    }
}



블로그 이미지

Link2Me

,
728x90

listView 내용을 텍스트로 저장하는 방법을 작성해봤다.

간단하게 작성하는 방법도 있지만, 원하는 열만 출력하고 싶은 경우가 있어서 이 부분을 고려해서 작성했다.

현재 읽어들인 파일명까지 인식하여 저장하는 것은 아직 구현을 못했다.


private void saveDataToolStripMenuItem_Click(object sender, EventArgs e)
{
    SaveFile();
}

private void SaveFile()
{
    SaveFileDialog sfd1 = new SaveFileDialog();
    sfd1.Title = "텍스트 파일 저장";
    sfd1.FileName = string.Empty;
    sfd1.Filter = "텍스트파일 (*.txt)|*.txt";
    if (sfd1.ShowDialog(this) == DialogResult.OK)
    {
        try
        {
            SaveData_listView(sfd1.FileName, listView1);
        }
        catch
        {
            MessageBox.Show("Excel 파일 저장중 에러가 발생했습니다.");
            return;
        }
        MessageBox.Show(Path.GetFileName(sfd1.FileName) + " 파일을 저장했습니다.");               
    }
}

private void SaveData_listView(string fileName, ListView LV)
{
    // Text 파일로 데이터 저장
    string delimeter = Environment.NewLine;  // 줄바꿈(개행문자)
    using (TextWriter textExport = new StreamWriter(fileName))
    {
        if (LV.Items.Count == 0)
        {
            MessageBox.Show("저장할 내용이 없습니다");
            return;
        }

        foreach (ListViewItem item in LV.Items)
        {
            for (int i = 0; i < item.SubItems.Count - 1; i++) // SubItems (열)을 전부 순환하는데 마지막은 제외
            {
                if (i != 1)  // 출력하고 싶지 않은 열 지정
                {
                    textExport.Write(item.SubItems[i].Text);
                    textExport.Write(";");
                    //textExport.Write(delimeter);  // 줄바꿈으로 처리하고 싶을 때
                }                       
            }
            textExport.Write(delimeter);
        }

        textExport.Flush(); // flush from the buffers
        textExport.Close();
    }
}


위 코드 파일 소스

Text_Export.cs



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

C# listView Checkbox 추가하는 방법  (2) 2015.10.04
C# listView Line Merge(행 병합)  (0) 2015.10.03
C# listView 행높이 지정 방법  (0) 2015.09.27
C# listView ContextMenu 에서 행 삭제  (0) 2015.09.26
C# ListView 기능 분석  (0) 2015.09.14
블로그 이미지

Link2Me

,
728x90

C# 에서 파일을 저장하고 저장된 파일명을 팝업창으로 보여주고 싶을 때



string filePath = @"C:\Dir\SubDir\file.txt";


string path = Path.GetDirectoryName(fileName);  //
string filename_with_ext = Path.GetFileName(fileName);  //
string filename_without_ext = Path.GetFileNameWithoutExtension(fileName);  //
string ext_only = Path.GetExtension(fileName);  //

DateTime dt = File.GetLastWriteTime(fileName); // 일/


간단 명료하게 함수로 만들어서 사용해도 된다.

private string getFileName(string filePath)
{
     return System.IO.Path.GetFileName(filePath);
}

private string getFilePath(string filePath)
{
     return System.IO.Path.GetDirectoryName(filePath);
}

private string getFileExt(string filePath)
{
     return System.IO.Path.GetExtension(filePath);
}


// 현재 디렉토리 경로 가져오기

string currentPath = System.IO.Directory.GetCurrentDirectory();


// 디렉토리 생성

public static void CreateDirectory(string filePath) 

    if (!Directory.Exists(filePath)) Directory.CreateDirectory(filePath); 


// 파일 삭제

public static void DeleteFile(string filePath) 

    if (File.Exists(filePath)) File.Delete(filePath);   //파일 삭제   
}


'C# > 문법 및 기능' 카테고리의 다른 글

C# 문자열 다루기 StringBuilder  (2) 2015.10.10
C# 문자열 분리 Split  (0) 2015.10.09
C# 변수 선언, 제어문과 자동완성 기능  (2) 2015.09.25
C# enum  (0) 2015.09.23
C# 과 VB 문법 차이  (0) 2015.09.22
블로그 이미지

Link2Me

,
728x90
listView 기능을 익히면서 MySQL DB에 있는 데이터를 가져와서 출력하는데, MySQL DB에는 저장하지 않고 화면상에서만 기능이 동작하도록 하면서 기능을 확인하니까 엄청 편하다.


C# listView 기본 값은 행간격이 너무 좁아서 좀 답답하다.




행높이를 이렇게 약간 넓게 조정하는 방법


private void SetHeight(ListView LV, int height)
{
      // listView 높이 지정
      ImageList imgList = new ImageList();
      imgList.ImageSize = new Size(1, height);
      LV.SmallImageList = imgList;
}


이 함수를 코드에 추가한다.

이제 SetHeight(listView1, 20); 을 listView_Table 함수에 한줄 추가해주면 된다.

20 숫자는 화면에 출력될 사이즈에 맞게 조절하면 된다.







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

C# listView Checkbox 추가하는 방법  (2) 2015.10.04
C# listView Line Merge(행 병합)  (0) 2015.10.03
C# listView 텍스트파일로 저장  (0) 2015.09.29
C# listView ContextMenu 에서 행 삭제  (0) 2015.09.26
C# ListView 기능 분석  (0) 2015.09.14
블로그 이미지

Link2Me

,
728x90

listView1 에서 마우스 우클릭하여 행을 추가, 삭제하고 싶다면 어떻게 해야 할까?

선택한 행만 삭제하도록 구현할 경우와 다중 삭제를 할 수 있도록 구현하는 방법이 각각 다르다.



ContextMenu 에 listView1 서 ContextMenuStrip 다.




이제 ContextMenu 항목을 추가한 다음에

private void lineDeleteToolStripMenuItem_Click(object sender, EventArgs e)
{
    // 선택한 Line 다중 삭제
    foreach (ListViewItem item in listView1.SelectedItems)
    {
        listView1.Items.Remove(item);
    }
    listView1.Update();
}

private void lineDeleteToolStripMenuItem_Click(object sender, EventArgs e)
{
     if (listView1.SelectedItems.Count > 0)   // 선택한 Line 만 삭제됨
     {
         listView1.SelectedItems[0].Remove();
         listView1.Update();
     }
}


이걸 ListView1 에서만 사용하는 것이 아니라 listView2 에서도 같이 사용하고자 하면 함수로 만드는게 좋다.

여러 행을 지울 때 지우고 난 이후 첫번째 행으로 선택되게 하려면 첫번째 선택한 행의 index 값을 구하면 된다.

선택한 행의 index 값을 알아보려면 아래와 같이 하면 된다.

for (int i = 0; i < LV.SelectedItems.Count; i++)
{
    MessageBox.Show(LV.SelectedIndices[i].ToString());
}

// ----- Line Delete Func ------ //

private void lineDeleteToolStripMenuItem_Click(object sender, EventArgs e)
{
    Delete_listView(listView1);
}

private void Delete_listView(ListView LV)
{

    if (LV.SelectedItems.Count <= 0)

    {

          MessageBox.Show("선택된 행이 없습니다");

          return;

    }

    int index = LV.SelectedIndices[0]; // 첫번째 선택 index   
    foreach (ListViewItem item in LV.SelectedItems)
    {
        LV.Items.Remove(item); 
// 선택한 행 삭제   

    }
    listView_No(LV);  // 번호 다시 매기기
    if (index > LV.Items.Count -1) // index 가 마지막 행보다 크면
    {
        index = LV.Items.Count -1;
    }
    LV.Items[index].Selected = true;
    LV.Items[index].EnsureVisible();
}

private void listView_No(ListView LV)
{
    // 번호 매기기
    for (int i = 0; i < LV.Items.Count; i++)
    {
        LV.Items[i].Text = (i + 1).ToString();
    }
}

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

C# listView Checkbox 추가하는 방법  (2) 2015.10.04
C# listView Line Merge(행 병합)  (0) 2015.10.03
C# listView 텍스트파일로 저장  (0) 2015.09.29
C# listView 행높이 지정 방법  (0) 2015.09.27
C# ListView 기능 분석  (0) 2015.09.14
블로그 이미지

Link2Me

,