using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
namespace automating_system_report
{
#region RAWDATASTRUCT
public class RAWDATASTRUCT
{
public int col, row; // FieldValue가 있던, raw 파일 내에서의 위치
public string FieldValue; // rawData 하나의 값
}
#endregion /RAWDATASTRUCT
#region RawDataLOADER
///
/// XML에 추가할 RAWDATA를 로드하고, list에 등록하는 클래스
/// fieldDelimiter의 값에 따라 필드구분을 하려고 했으나, 기본값 " "으로만 동작.
///
class RawDATALoader:FileManager
{
#region public Member
public string filedDelimiter = " ";//텍스트파일의 필드구분자, 기본값 spacebar 를 필드 구분으로 함.
public List rawdataList = new List();
#endregion /public Member
#region public Method
public bool Load(string filename) //
{
FullPath = filename;
if (ExistFile)
{
FileStream fs = File.OpenRead(filename);
StreamReader sr = new StreamReader(fs);
int row = 0;// 줄 수
while (sr.Peek() > -1) //한줄 한줄 배열에 저장
{
SaveToList(sr.ReadLine(), row);
row ++;
}
sr.Close();
fs.Close();
return true;
}
return false;
}
public string[,] To2DArray()
{
int SizeCol = rawdataList[rawdataList.Count - 1].col;
int SizeRow = rawdataList[rawdataList.Count - 1].row;
string[,] rtnArray = new string[SizeRow + 1, SizeCol + 1];
int i = 0;
foreach (RAWDATASTRUCT r in rawdataList)
{
rtnArray[r.row, r.col] = r.FieldValue;
}
return rtnArray;
}
#endregion /public Method
#region private Method
private bool SaveToList(string buf,int row)
{
int whereIsDelimiter = 0; //필드구분자의 문자열 내에서 위치
int col = 0; // 필드 순번..
string cropElement;
buf=buf.Trim(); //앞이나 뒤에서 공백을 필드로 오인하는 것을 방지하기 위해 앞뒤 공백 삭제
try
{
do
{
whereIsDelimiter = buf.IndexOf(filedDelimiter); //맨 왼쪽 필드 한 개의 길이를 찾기 위해,공백을 찾음.
if (whereIsDelimiter > -1) //공백을 찾은 경우
{
cropElement = buf.Substring(0, whereIsDelimiter); // 찾은 단일 필드를 저장하기 위해 임시로 변수에 저장
buf = buf.Remove(0, whereIsDelimiter); //다음 반복을 위해 buf에서 크롭한 부분 제거
}
else//공백을 못찾은 마지막 필드인 경우
{
cropElement = buf;
}
RAWDATASTRUCT fieldAdd = new RAWDATASTRUCT(); //crop한 필드를 저장하기 위해 임시 RAWDATASTRUCT를 만듬.
fieldAdd.FieldValue = cropElement;
fieldAdd.row = row; //텍스트 문서상의 줄 위치, 2차원 배열 생성시 사용됨
fieldAdd.col = col; //컬럼값, 2차원 배열 생성시 사용됨
rawdataList.Add(fieldAdd);//crop한 필드를 리스트에 저장
buf = buf.TrimStart(); //문자열 앞의 의미없는 공백제거
col += 1;
} while (buf != null & whereIsDelimiter > -1); //buf가 null일 때까지, 더 이상 필드가 없을 때까지 반복.
return true;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return false;
}
}
#endregion /private Method
}
#endregion /RawDataLOADER
}
//
2012-06-28
C# 텍스트파일을 읽어서 2차원 배열로 만들기
성능 데이터가 기록된 텍스트 파일을 열어서 엑셀에 붙여넣기 하기 위해 만듬.
2012-06-27
C# 문자열의 yy, mm, dd를 지정한 날짜데이터의 숫자로 변환하기
파일을 날짜별로 생성해야 해서 만들었다.
public string ConvertDateInString(string filenameFormat, DateTime targetdate)
string filenameFormat에 "yymmdd_파일이름_yymmdd-1.xlsx"를 넘겨주면,
targetdate의 년월일의 숫자데이터로 변경한다.
return string은 변경된 이름이다.
(소문자 yy, mm, dd 또는 yyyy만 인식한다.)
public string ConvertDateInString(string filenameFormat, DateTime targetdate)
string filenameFormat에 "yymmdd_파일이름_yymmdd-1.xlsx"를 넘겨주면,
targetdate의 년월일의 숫자데이터로 변경한다.
return string은 변경된 이름이다.
(소문자 yy, mm, dd 또는 yyyy만 인식한다.)
/// 지정한 날짜 데이터의 숫자로 yy, mm ,dd 또는 yyyy를 replace 함.
///
using System;
namespace automating_system_report
{
class DateStringConverter
{
#region global var
FindNumberInString fn = new FindNumberInString(); // source에서 숫자 부분을 검출, +나 - 기호의 뒤에 숫자가 위치하면, 날짜 데이터에 가감하기 위해 선언
#endregion global var
///
/// filenameFormat을 yy, dd, mm의 해당 문자열을 targetdate의 날짜 데이터로 바꿈
/// 파라미터 설명은 2012년 6월 26일을 예로 함.
///
///
ex) yyyymmdd점검일지yy-mm-dd-1.xlsx
///
ex)날짜 데이터(2012-06-26)
/// ex) 20120626점검일지12-06-25.xlsx
public string ConvertDateInString(string filenameFormat, DateTime targetdate)
{
fn.FindNumber(filenameFormat);
DateTime convertedDate=targetdate;
filenameFormat = RecursiveReplaceDate(filenameFormat, "dd", ref targetdate); //filenameFormat의 dd부분을 days로 변경
filenameFormat = RecursiveReplaceDate(filenameFormat, "mm", ref targetdate); //filenameFormat의 mm부분을 months로 변경
if(filenameFormat.LastIndexOf("yyyy")>-1)
filenameFormat = RecursiveReplaceDate(filenameFormat, "yyyy", ref targetdate); //filenameFormat의 yyyy부분을 years로 변경
else if(filenameFormat.LastIndexOf("yy")>-1)
filenameFormat = RecursiveReplaceDate(filenameFormat, "yy", ref targetdate); //filenameFormat의 yy부분을 years로 변경
if ((filenameFormat.IndexOf("yy")>-1) ||(filenameFormat.IndexOf("mm")>-1) ||(filenameFormat.IndexOf("dd")>-1) )
{
filenameFormat=ConvertDateInString(filenameFormat,targetdate);
}
return filenameFormat;
}
public string RecursiveReplaceDate(string source, string repStr, ref DateTime convertedDate)
{
int whereIsrepStr=-1; // repStr이 있는 위치를 저장할 변수
int adjustLocPredication=-1; // repStr뒤에 +나 -로 조정할 기호가 있을 위치를 비교하기 위한 변수
int adjustVal=0; // +나 -로 조정할 기호가 있다면 조정할 수치
int adjustLength=0; // +나 - 기호부터 ~ 수치까지 길이
string dating=""; //년월일에 변경할 숫자 문자.
string prestr; //숫자로 변경할 날짜부분의 앞
string poststr;//숫자로 변경할 날짜부분의 뒤
DateTime convertedDate;// targetdate에서 +,-로 변경한 날짜데이터.
try
{
whereIsrepStr = source.LastIndexOf(repStr); //뒤에서부터 repStr을 검색, 위치를 기억
}
catch { whereIsrepStr = -1; } //repStr을 source문자열에서 못찾을 경우
if (whereIsrepStr > -1)// 바꿀 대상인 repStr이 문자열에 있으면, 숫자로 변환하기 위해 아래를 수행
{
adjustLocPredication = whereIsrepStr + repStr.Length; //adjustLocPredication는 문자열에서 repStr위치한 다음 칸
// 먼저 repStr뒤에 +나 - 기호의 조정자가 있는지 검색
foreach (FindNumberInString.NumberInStringSTRUCT n in fn.ListNumber) //filenameFormat의 숫자의 값과 위치를 담고 있는 ListNumber를 foreach
{
//Trace.WriteLine(n.StartIndex);
if (n.StartIndex == adjustLocPredication + 1) //foreach수행한 요소마다 위치가 +, - 기호 뒤에 위치하는지 비교
{ //(+,-기호 위치 바로 뒤에 오는 숫자는 날짜데이터에서 변경할 값으로 인식)
adjustVal = Int32.Parse(n.NumberString); //adjustVal은 날짜에서 변경할 값
// +기호인지 -기호인지 확인
char[] sign = source.ToCharArray();
if (sign[adjustLocPredication] == '-')
{
adjustVal *= (-1); //음수
adjustLength=n.Length+1;
}
else if (sign[adjustLocPredication ] == '+')
{
adjustLength=n.Length+1;
}
else { adjustVal = 0; } // + , - 기호가 없으면 날짜에서 변경할 값이 아닌 일반 숫자로 받아들임
}
}
switch (repStr) //repStr의 종류에 따라 위에서 찾은 adjustVal만큼 조정후, 년월일에 해당하는 문자열을 substring
{
case "dd":
convertedDate = targetdate.AddDays(adjustVal);
dating = convertedDate.Date.ToString().Substring(8, 2);
break;
case "mm":
convertedDate = targetdate.AddMonths(adjustVal);
dating = convertedDate.Date.ToString().Substring(5, 2);
break;
case "yyyy":
convertedDate = targetdate.AddYears(adjustVal);
dating=convertedDate.Date.ToString().Substring(0,4);
break;
case "yy":
convertedDate= targetdate.AddYears(adjustVal);
dating=convertedDate.Date.ToString().Substring(2,2);
break;
}
if (dating!="")
{
prestr = source.Substring(0, whereIsrepStr); //변경할 문자열을 제외한 앞부분
poststr = source.Substring(whereIsrepStr + repStr.Length + adjustLength);//변경할 문자열을 제외한 뒷부분
source = prestr + dating + poststr;//앞부분 + 날짜문자열 + 뒷부분을 다시 source에 저장
}
}
return source;
}
}
}
//
2012-06-25
C# 배열의 내용을 Excel sheet에 채우기
////// Excel /// .Application 액셀 어플리케이션 자체 /// ._Workbook 워크북 = 엑셀 파일 /// .Sheets 엑셀 시트의 배열 /// ._Worksheet 액티브된 단일 시트 /// .Range 편집범위 /// using System; using System.Text; using Excel=Microsoft.Office.Interop.Excel; using System.Windows.Forms; using System.Diagnostics; namespace automating_system_report { class ExcelUpdater:FileManager { #region const var #endregion const var #region public global var public Excel.Application objApp = new Excel.Application(); public Excel._Workbook objBook; #endregion public global var #region 생성자&소멸자 public ExcelUpdater() //기본 생성자 { } public ExcelUpdater(string sourcefile, string targetfile)//템플릿 파일과 생성할 파일을 파라미터로 주고 open { LoadFile(sourcefile,targetfile); } ~ExcelUpdater() { //PRB: Visual Studio .NET 클라이언트에서 자동화 후에 Office 응용 프로그램이 종료되지 않는다(http://support.microsoft.com/kb/317109) UnLoadFile(); } #endregion 생성자&소멸자 #region public Method ////// updateSheet, 배열의 내용으로 sheet를 채운다. /// 줄과 칸을 각각 받았으나 "A1" 형식의 위치를 받기로 변경함. /// /// 데이터를 붙여넣을 sheet번호. 1부터 시작 /// 붙여넣기 시작할 위치, (예: "A1") /// 붙여넣을 내용, 문자열 2차원 배열 public bool updateSheet(int sheetNumber, string writeStartLoc, ref string[,] rawdata) { try { Excel.Sheets objSheets = objBook.Sheets; Excel._Worksheet objSheet = objSheets[sheetNumber]; Excel.Range range; range = objSheet.get_Range(writeStartLoc); range = range.get_Resize(rawdata.GetLength(0), rawdata.GetLength(1)); range.set_Value(null, rawdata); return true; } catch(Exception e) { MessageBox.Show(e.Message); return false; } } /// col과 row로 호출하면, "A1"형식으로 변환. /// 데이터를 붙여넣을 sheet번호. 1부터 시작 /// 붙여넣기 시작할 줄, 1부터 시작 /// 붙여넣기 시작할 칸, 0부터 시작(0~16383) /// 붙여넣을 내용, 문자열 2차원 배열 public void updateSheet(int sheetNumber,int writeStartRow,int writeStartCol,ref string[,] rawdata) { // Row와 Col을 저장할 변수들 string writeStartLoc; writeStartLoc = DecToAlphabet(writeStartCol) + writeStartRow.ToString(); // row 1, col 0일 경우 loc은 "A1" updateSheet(sheetNumber, writeStartLoc, ref rawdata); } public bool LoadFile(string TemplateXlsFile, string CopiedXlsFile) // source파일의 사본을 만들고 로드 { FullPath = CopiedXlsFile; try // 엑셀파일이 열려있을 경우 오류 { //System.IO.File.Delete(FullPath); System.IO.File.Copy(TemplateXlsFile, CopiedXlsFile, true); //템플릿을 복사 objBook = objApp.Workbooks.Open(CopiedXlsFile); // objApp.Visible = true; // Excel app의 visible=false; return true; } catch(Exception e) { MessageBox.Show(e.Message); return false; } } public void UnLoadFile() // 엑셀 프로세스를 저장없이 그냥 닫을 때 사용. { objBook = null; objApp = null; } public bool CloseAndSave() // 엑셀 파일 저장. { try { objBook.Save(); objBook.Close(); objApp.Quit(); //프로세스에서 삭제 return true; } catch (Exception e) { MessageBox.Show(e.Message); return false; } } ////// 10진수 컬럼 값을 엑셀에서 사용하는 컬럼 값 처럼, 알파벳으로 변환 /// /// 0은 A, Z는 25 ///public string DecToAlphabet(int num) { int rest; //나눗셈 계산에 사용될 나머지 값 string alphabet; //10진수에서 알파벳으로 변환될 값 byte[] asciiA = Encoding.ASCII.GetBytes("A"); // 0=>A rest = num % 26; // A~Z 26자 asciiA[0] += (byte)rest; // num 0일 때 A, num 4일 때 A+4 => E alphabet = Encoding.ASCII.GetString(asciiA); //변환된 알파벳 저장 num = num / 26 -1; // 그 다음 자리의 알파벳 계산을 재귀하기 위해, 받은 수/알파벳수 -1 (0은 A라는 문자값이 있으므로 -1을 기준으로 계산함) if (num > -1) { alphabet = alphabet.Insert(0, DecToAlphabet(num)); //재귀 호출하며 결과를 앞자리에 insert } return alphabet; // 최종값 return } /// int input=Int32.Parse(textBox1.Text.ToString()); /// Trace.WriteLine(input+"=> "+ xlsmaker.DecToAlphabet(input)); /// 결과 /// 0=> A /// 27=> AB /// 16383=> XFD #endregion public Method } } //
2012-06-22
C# Excel worksheet.Cells의 성능 느림.
출처: http://support.microsoft.com/kb/306023/ko
전에 올린 Cell에 직접 데이터를 입력하는 방법은 쉬운 방법이지만,
대량의 데이터를 옴기기엔 속도가 매우 느리다.(문서에서는 300줄을 기준으로 삼음)
8600줄의 데이터를 엑셀파일로 옴겼더니, 20분째 어플리케이션은 행이 걸려있고 엑셀문서는 한줄 한줄 타이핑 잘하는 사람이 입력하는 걸 빨리감기 하는 정도 속도로 쓰고 있다.
Cell에 직접 데이터를 입력하는 방식의 성능과 관련해 검색을 해보니, 이 방법은 대량데이터를 옴기기엔 적합하지 않다고 한다.
이렇게 입력할 데이터가 많을 경우 다른 방법을 제시했는데,
1. 배열을 워크시트로 전송
2. ADO 레코드를 워크시트로 전송
3. Windows 클립보드를 이용한 전송
이렇게 3가지 방법이다.
예제코드는 출처로 가보길 바람.
C# 숫자 컬럼값을 액셀 알파벳컬럼값으로 변환
숫자 컬럼 값을 엑셀에서 사용하는 알파벳으로 변환해 봄.
///
/// 10진수 컬럼 값을 엑셀에서 사용하는 컬럼 값 처럼, 알파벳으로 변환
///
///
///
public string DecToAlphabet(int num)
{
int rest; //나눗셈 계산에 사용될 나머지 값
string alphabet; //10진수에서 알파벳으로 변환될 값
byte[] asciiA = Encoding.ASCII.GetBytes("A"); // 0=>A
rest = num % 26; // A~Z 26자
asciiA[0] += (byte)rest; // num 0일 때 A, num 4일 때 A+4 => E
alphabet = Encoding.ASCII.GetString(asciiA); //변환된 알파벳 저장
num = num / 26 -1; // 그 다음 자리의 알파벳 계산을 재귀하기 위해, 받은 수/알파벳수 -1 (0은 A라는 문자값이 있으므로 -1을 기준으로 계산함)
if (num > -1)
{
alphabet=alphabet.Insert(0,DecToAlphabet(num)); //재귀 호출하며 결과를 앞자리에 insert
}
return alphabet; // 최종값 return
}
///
/// int input=Int32.Parse(textBox1.Text.ToString());
/// Trace.WriteLine(input+"=> "+ xlsmaker.DecToAlphabet(input));
/// 결과
/// 0=> A
/// 27=> AB
/// 16383=> XFD
//
2012-06-13
C# Excel
액셀 cell에 직접 입력 하는 방법의 예.
/// 방법: Visual C# 2010 기능을 사용하여 Office Interop 개체에 액세스(C# 프로그래밍 가이드)
/// http://msdn.microsoft.com/ko-kr/library/dd264733
/// 솔루션-> 참조-> "COM" 탭 -> "Microsoft Excel 14.0 Object Library" 추가
///
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace sample_excel
{
public class Account
{
public int ID { get; set; }
public double Balance { get; set; }
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Create a list of accounts.
var bankAccounts = new List {
new Account {
ID = 345678,
Balance = 541.27
},
new Account {
ID = 1230221,
Balance = -127.44
}
};
// Display the list in an Excel spreadsheet.
DisplayInExcel(bankAccounts);
}
static void DisplayInExcel(IEnumerable accounts)
{
var excelApp = new Excel.Application();
// Make the object visible.
excelApp.Visible = true;
// Create a new, empty workbook and add it to the collection returned
// by property Workbooks. The new workbook becomes the active workbook.
// Add has an optional parameter for specifying a praticular template.
// Because no argument is sent in this example, Add creates a new workbook.
excelApp.Workbooks.Add();
// This example uses a single workSheet. The explicit type casting is
// removed in a later procedure.
Excel._Worksheet workSheet = (Excel.Worksheet)excelApp.ActiveSheet;
// Establish column headings in cells A1 and B1.
workSheet.Cells[1, "A"] = "ID Number";
workSheet.Cells[1, "B"] = "Current Balance";
workSheet.Cells[1, "C"] = "=SUM(A2:B2)";
var row = 1;
foreach (var acct in accounts)
{
row++;
workSheet.Cells[row, "A"] = acct.ID;
workSheet.Cells[row, "B"] = acct.Balance;
}
workSheet.Columns[1].AutoFit();
workSheet.Columns[2].AutoFit();
}
}
}
//
...
피드 구독하기:
글 (Atom)