[C#] 엑셀과 연동 -_-a C# 2010. 4. 6. 11:58
엑셀하고 연동하다가.. 그 부분을 남겨두는게 좋을 것 같아서..

포스팅.. 이게 대체 얼마만인가 ㅠㅠ

일단 제일 먼저 참조를건다. 8.0과 9.0이 있었던거 같은데..

오피스 버전에 따라 다른 것이었다

using Excel = Microsoft.Office.Interop.Excel;

선언을 살포시 해 준 다음..

Excel.Workbook workbook = null;
Excel.Worksheet worksheet = null;
Excel.Application application = null;

선언을 해준다.

object missing = System.Reflection.Missing.Value;
object fileName = @"파일.xls";
위에 파일 이름은 파일이 저장되는 경로이다.

그리고 처리를 해서 엑셀 파일 양식을 읽어온다.

application = new Excel.Application();
application.Visible = false; 

엑셀창이 나타나지 않고 작업을 진행하기 위해서 처리를 하고난 다음

workbook = application.Workbooks.Open(@"파일.xls", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
작업 양식이 저장되어 있는 엑셀을 열어주고

worksheet = (Excel.Worksheet)workbook.Sheets["시트명"];

해당 시트를 생성하고 난 다음 작업을 시작하면 된다

get_Range는 해당하는 범위를 가져온다.

예를 들어서 다음과 같이 하면
worksheet.get_Range("A12", "H12").Insert(Excel.XlInsertShiftDirection.xlShiftDown, Type.Missing);
해당 라인이 추가가 된다. 당연히 빈 공백이다.

그리고 해당하는 범위의 색을 바꾸자고 한다면
worksheet.get_Range("A12", "H12").Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.White);
형식으로 해 주면 된다.

해당하는 셀에 직접 입력하는 경우는
worksheet.Cells[12, 1] = i.ToString();
형식이다.

해당 파일을 열어서 그 데이터를 가져오고자 할 경우에는
worksheet.Cells.get_Range("B7", "B7").Text.ToString();
과 같이 해 주면 된다.

그리고 마지막으로 작업을 끝내고 난 다음 저장을 할 경우에
workbook.SaveAs(fileName, Excel.XlFileFormat.xlWorkbookNormal, missing, missing, missing, missing, Excel.XlSaveAsAccessMode.xlShared, Excel.XlSaveConflictResolution.xlLocalSessionChanges, missing, missing, missing, missing);
여기서 fileName은 포스팅 위쪽에 명시된 대상 파일이다.

위와같은 처리를 해서 저장을 해 주면 된다!!

그거 말고도 참.. 많던데.. 쉽지 않은 작업.. 이였다.. 왜 -_-;; 몰랐으니까;;


[C#]DoEvent() C# 2010. 3. 6. 13:42
아우.. 이놈 땀시 하루를 그냥 보냈다..

일반적으로 루프를 돌면서 어느 정도 부하가 돌아가면..

App가 응답없음이라는 부분을 보여준다.

이럴 때 그 루프에 DoEvent() 처리를 해 주면!!

윈도우의 이벤트 큐에서 어떠한 이벤트가 들어오면 그것을 처리 해 주고 다시 돌아와서 작업을 하게 해 준다.

이 얼마나 좋은 것인가..

매번 Invoke나 BeginInvoke를 이용하여 처리 해도 안되는 것들을..

저거 한방에.. 그냥 스윽 한다..

역시나.. 이번에도 삽질 끝에 메서드 하나.. ㅠㅠ

오늘도 삽질은 계속 이어진다!!
[C#] Grid에서의 인덱스 C# 2009. 10. 7. 18:04
보편적으로 그리드 뷰 또는 리스트 뷰를 많이 쓴다

지금은 그 그리드 뷰의 인덱스를 가져오는 것에 대해 잠시 끄적여봐야겠다.

보통 마우스 더블클릭 또는 클릭 이벤트로 각각의 로우 인덱스를 얻으려고 하지만

이벤트 쪽엔 그러한 내용이 없다.

즉 셀에 해당하는 이벤트에는 존재한다.

Rowindex 이다.

사용하는 예는 e.RowIndex 지정하면 int 값으로 그 로우의 인덱스 값을 얻어온다.

리스트 뷰와 그리드 뷰의 장단점은 있지만,

이벤트를 먹여서 원하는 값에 대한 처리를 하기에는 그리드 뷰가 다루기가 더 쉬운 듯 하다.

e라는 인자 값으로 보통 이벤트의 변수가 뜨는데 각기 데이터를 잘 살펴보면 손쉽게 원하는 결과를 얻을 수가 있다.
ArrayList를 사용하는 개발자들이 많을 것이다.

근데 여기에 값을 집어넣으면 object 타입으로 들어간다.

이것을 object 배열 형으로 바꿔주는 것이 ToArray() 이다.

하지만 이것을 ToString() 이나 ToInt32() 등을 해서 원하는 타입으로 바꾸는 것은.. 엄청나게 귀찮은 작업이다.

그래서 이것을 바로 변환 시키는 팁이 다음과 같다.

예를들어 string[] 형으로 저장을 하고자 한다면,

string[] ToStringArray = (string[])ArrayListValue.ToArray(typeof(string));

이렇게 한다면 object[] 형으로 저장된 것들이 string[] 형으로 바뀐다.

1. ListView

ListView의 Item 아래에 집어 넣는다. 솔직히.. Datagrid 보다 이뻐 보인다.

2. DataGrid의 DataTable 이용

DataTable을 만들어서 컬럼을 직접 넣어줘서 연결해 주거나

Row를 추가 해서 해 준다.

3. Datagrid의 DataSet을 이용

솔직히 이것이 제일 나은 듯. 하지만 컬럼명을 지정할 수가 없다.

조회되는 컬럼 자체가 붙어버린다.

어디다가 투표를 해야할지 참.. ㅎㅎ

각기 장단점이 있다보니.. -_-a 좀 갈등이 되네요 ㅎㅎ

솔직히 트랜잭션을 이용해서 서로 다른 DBMS에서 불러오는 것만 아니라면

DataSet을 추천하지만..

아닐 경우는 -_- 어쩔 수 없이 ListView와 DataTable을 이용해야겠죠??

그 외의 방법을 아시는 분들은 꼬릿말 부탁 드립니다 ㅎㅎ

다른 사람들은 어떻게 쓰는지 궁금해요 +_+

C#에서는 몇몇 클래스를 통하여 간단히 작성할 수가 있다.

그 예제 코드는 다음과 같다. (MSDN에서 발췌 해 왔다. 보면 -_-;; 알 사람들은 다 알 듯..)

[예제]

        private const String filename = "Test.xml";
        private const String stylesheet = "myStyleSheet.xsl";

            XslTransform xslt = new XslTransform();
            xslt.Load(stylesheet);
            XPathDocument xpathdocument = new XPathDocument(filename);
            XmlTextWriter writer = new XmlTextWriter("testResult1.xml", Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            xslt.Transform(xpathdocument, null, writer, null);

여기서 보면 xslTransform을 생성하고 해당 xsl 파일을 로드한다.

물론 이것은 사용자가 정의를 해 줘야한다.

필자가 테스트한 myStyleSheet.xsl의 내용은 다음과 같다.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="Students/Student">
<name><xsl:value-of select="Name"></xsl:value-of></name>
<value><xsl:value-of select="Value"></xsl:value-of></value>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Test.xml의 내용은 다음과 같다.

<?xml version="1.0" encoding="utf-8"?>
<Students>
<Student>
<Name>test</Name>
<Value>10</Value>
</Student>
</Students>

이것을 실행하여 새로운 파일을 생성한다면 그 안의 내용은

<name>test</name>
<value>10</value>

로 저장이 된다.

이를 통하여 새로운 데이터들을 정의하여 원하는 방식으로 뽑아 쓸 수 있다.

MSDN은 역시 보물 창고다!! ㅠ_ㅠ

무턱대고 네이버나 이런데서 찾는 사람들이 없기를 바라며..


흠.. 일반적으로 닷넷에서 정해진 폼이 있다. 하지만 원하는 메세지들 내용 등을 바꾸자면 아래 예제 코드와 같이 가능하다.

*예제 코드*

public class MessageBoxChange
    {
        delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(int hook, HookProc callback, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll")]
        static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll")]
        static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        static extern IntPtr GetDlgItem(IntPtr hDlg, DialogResult nIDDlgItem);

        [DllImport("user32.dll")]
        static extern bool SetDlgItemText(IntPtr hDlg, DialogResult nIDDlgItem, string lpString);

        [DllImport("kernel32.dll")]
        static extern uint GetCurrentThreadId();

        static IntPtr g_hHook;

         string yes;
         string no;

        //OK
        public DialogResult Show(string text, string caption, string ok)
        {
            this.yes = yes;
            this.no = no;
            g_hHook = SetWindowsHookEx(5, new HookProc(HookWndProc), IntPtr.Zero, GetCurrentThreadId());
            return MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Question);
        }

        //YES NO
        public DialogResult Show(string text, string caption, string yes, string no)
        {
            this.yes = yes;
            this.no = no;
            g_hHook = SetWindowsHookEx(5, new HookProc(HookWndProc), IntPtr.Zero, GetCurrentThreadId());
            return MessageBox.Show(text, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        }

        public int HookWndProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            IntPtr hChildWnd;

            if (nCode == 5)
            {
                hChildWnd = wParam;

                if (GetDlgItem(hChildWnd, DialogResult.OK) != null)
                    SetDlgItemText(hChildWnd, DialogResult.OK, this.yes);

                if (GetDlgItem(hChildWnd, DialogResult.Yes) != null)
                    SetDlgItemText(hChildWnd, DialogResult.Yes, this.yes);

                if (GetDlgItem(hChildWnd, DialogResult.No) != null)
                    SetDlgItemText(hChildWnd, DialogResult.No, this.no);

                UnhookWindowsHookEx(g_hHook);
            }
            else
                CallNextHookEx(g_hHook, nCode, wParam, lParam);

            return 0;
        }
    }

당연히 주의해야할 점은 네임스페이스다.

이들은 Forms를 참조하는 다이얼로그와 P-INVOKE를 이용하기 위한 InteropServices 의 네임스페이스를 참조해야한다.

이를 꼭 명심하자!!

1. BackgroundWorker는 ComponentModel 네임스페이스를 이용해야 쓸 수 있다.

2. BackgroundWorker bw = new BackgroundWorker(); 로 생성한다.

3. bw.WorkerSupportsCancellation = true; 설정을 해 준다.

4. bw.DoWork += new DoWorkEventHandler(bw_DoWork); 의 이벤트 핸들러를 생성한다.

5. bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);의 이벤트 핸들러를 생성한다.

6. DoWork 내부에 쓰레드에 이용할 내용을 첨부한다.

7. RunWorkerCompleted 내부에 쓰레드 종료시 이용할 내용을 첨부한다.

if (e.Error != null){} 에러 발생 시 처리
else if (e.Cancelled){bw.CancelAsync();}사용자에 의해 종료 되었을 시 처리
else{}정상 종료 되었을 시 처리

물론 이 BackgroundWorker를 실행하기 위해서는 bw.RunWorkerAnsync(); 처리를 해 줘야한다.

게시글 중 하나 이와 유사한 글이 있다. 그 부분은 단시 쓰는 방법에 대한 것만 나와있다.

쓰레드가 완료 된 처리 내용에 대한 것은 없는 껍데기에 불과 하다는 이야기다.

앞으로 좀 더 잘 알아보고 블로깅을 해야지.. ㅠ_ㅠ 이거 원..
[C#]ComboBox 자동 완성! C# 2009. 6. 12. 14:37

흔히들 검색하다보면 한글자 치면 주르륵 내용이 나온다

그와 같이 콤보 박스도 가능하다.

물론 텍스트 박스도 TextChange 이벤트를 이용하여 가능하다.

하지만 데이터베이스와 연결이 되어있어야한다는 치명적인.. 약점이 ...

절차는 다음과 같다

1. AutoCompleteCustomSource에 컬렉션을 등록한다.

2. AutoCompleteMode에서 원하는 성격의 방식을 선택한다. 3가지 방식이 있다.

3. AutoCompleteSource에서 CustomSource를 선택한다.

그렇게 하면!! 된다!!

프레임워크 상에서 편하게 제공해주니.. -_- 그저 감사할 뿐이다 ㅎㅎ
[C#]Indexer ?? -_-;; C# 2009. 6. 10. 17:49
이거.. 좀 망설였다 -_-;;

왜!! 객체를 생성해 두고 -_- 왜!! .....

그놈의 배열을 이용하는 것인가 하고!!

뭐.. 이유야 있겠지만..

객체에 대한 생성을 하고 한다는게 조금 희안하기는 했다.

일단 먼저

class IndexClass<T>
{
   string[] T= new string[10];
}

라는 Index를 위한 클래스를 둔다

보통 우리는 객체를 생성해서 obj.indexArray로 접근한다!! 단!! public 일 때만 가능한 일이다.

하지만 private로 접근 한정자가 붙는다면.. 이 방법을 써야한다.

그래서 이 것을 쓰는가 보다!!

public T this[int i]
    {
        get
        {
            return indexArray [i];
        }
        set
        {
            indexArray [i] = value;
        }
    }

이 부분이 Index 클래스에 포함된다면!!

IndexClass<string> index = new IndexClass<string>();
index[0] = "인덱스를 통한 배열 접근";

이렇게 값을 할당 할 수도 있고

Console.WriteLine(index[0]);

해서 이용 할 수도 있다!!

필자는 제네릭을 이용해서 예제를 나타낸 것이지만..

그냥 이용하는 타입인 string으로 처리해서 한다해도!!

가능합니다~ ^_^