C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[1093] [Controls] TSV (Tab Separated Value) 와 StringGrid 그리고 엑셀 연동
장성호 [nasilso] 10186 읽음    2012-06-15 11:04
음..

바로 밑에 CSV 관련해서 글을 올린김에
TSV(Tab Separated Value) 관련해서도 적어본다

@TSV란 ?

  말그대로 Tab으로 구분된 값을 얘기한다.
  CSV에 Comma대신 Tab이 들어간것 뿐이다.

@TSV 파싱은?

CSV는 StringList에 CommaText 라는 프로퍼티를 이용해 쉽게 파싱이 가능한데..
TSV는 어떻게 쉽게 하는 방법이 없을까?

TSV도 TStringList로 쉽게 파싱이 가능하다.

TStringList *lst=new TStringList;
lst->Delimiter = '\t';
lst->DelimitedText = "하나\t둘\t셋\t넷\t다~섯";
lst->StrictDelimiter = true;
for(int i=0;iCount;i++)
{
   ShowMessage(lst->Strings[i]);
}
delete lst;


@TabText 를 만들려면?

CommaText를 만드는 방법과 비슷한 방법으로
TabText도 쉽게 만들수 있다.

TStringList *lst=new TStringList;
lst->Add("하나");
lst->Add("둘");
lst->Add("셋");
lst->Add("네 엣");
lst->Add("다아... 섯");
lst->Delimiter = '\t';
lst->StrictDelimiter = true;
ShowMessage(lst->DelimitedText );  //이렇게 가져오면 된다.
delete lst;



@TabText 파싱에 주의할점

StringList에는StrictDelimiter 라는 프로퍼티가 있다.
이걸 활성화 시켜놓지 않으면
문자열에서 space부분을 기본적인 구분자로 처리해 버리는 문제가 있다.


@TSV파일을 StringGrid로 읽으려면..

자 그럼 TSV파일을 Grid로 읽어오는 함수를 작성해보자
앞에 설명한 원리들을 이용하면 쉽게 구현이 가능하다.

//---------------------------------------------------------------------------
// TSVFile을 읽어서 StringGrid에 넣는 함수
//---------------------------------------------------------------------------
void __fastcall LoadFromTSVFile(TStringGrid *sGrid,String sTSVFile)
{
	if(!FileExists(sTSVFile))return;

	TStringList *sLst=new TStringList;
	TStringList *sCols=new TStringList;

	try
	{
		sLst->LoadFromFile(sTSVFile);
		sGrid->RowCount=sLst->Count;

		sCols->StrictDelimiter = true;
		sCols->Delimiter = '\t';
		for(int i=0; i < sLst->Coun t ;i++)
		{
			sCols->DelimitedText=sLst->Strings[i];
			if( sCols->Count > sGrid->ColCount )
			{
				sGrid->ColCount = sCols->Count;
			}
			sGrid->Rows[i]->Assign(sCols);
		}
	}
	__finally
	{
		delete sLst;
		delete sCols;
	}
}



@ StringGrid의 내용을 TSV파일로 저장하기

//---------------------------------------------------------------------------
// StringGrid의 내용을 TSVFile로 저장하는 함수
//---------------------------------------------------------------------------
void __fastcall SaveToTSVFile(TStringGrid *sGrid,String sTSVFile)
{
	TStringList *sLst=new TStringList;
	TStringList *sCols=new TStringList;
	try
	{
		sCols->StrictDelimiter = true;
		for(int i=0; i < sGrid->RowCount ; i++ )
		{
			sCols->Assign( sGrid->Rows[i ]);
			sCols->Delimiter = '\t';       //Assign할때 Delimiter까지 바뀌수 있으므로, 다시 설정해줘야함
			sLst->Add(sCols->DelimitedText);
		}
		sLst->SaveToFile(sTSVFile);
	}
	__finally
	{
		delete sCols;
		delete sLst;
	}
}



저장할땐 TSV보다는 xls로 하면 Excel프로그램에서 곧바로 열어볼수가 있다.

//---------------------------------------------------------------------------
// 사용은 이렇게...
void __fastcall TForm1::Button3Click(TObject *Sender)
{
	SaveToTSVFile(StringGrid1,"D:\\test.xls");
}
//---------------------------------------------------------------------------




@Clipboard를 이용해 Excel과 연동하기
그런데 Grid의 내용을 TSV파일로 부터 읽어오는 일은 실제로 별로 많지 않다.

하지만 엑셀(Excel)에서 Cell을 선택해서 Copy한후에
그것을 Grid에 곧바로 붙여넣기 하고 싶을때는 많이 활용될수 있지 않을까 싶다.


Excel에서 Cell을 선택해서 Copy하면 TSV로 Clipboard에 저장된다.


TSV로 Clipboard에 저장하고
Clipboard에 있는 Text포멧의 TSV문자열을 읽어올수 있다면..
Grid와 엑셀이 자연스럽게 Copy&Paste가 동작할 것이다.



@Grid의 선택된 Cell을 ClipBrd로 copy하기

자 그럼 Grid의 Selection-Rect의 내용을 Clipboard로 copy하는 코드를 작성해보자

//---------------------------------------------------------------------------
// Grid의 String을 Tab-Text(TSV)로 된 Clipboard의에 Copy
//---------------------------------------------------------------------------
void __fastcall CopyGridToClipbrd(TStringGrid *Grid,bool bContainHeader)
{
	TGridRect sRec=Grid->Selection;
	TStringList *sLst=new TStringList;
	TStringList *sCols=new TStringList;
	try
	{
		sCols->StrictDelimiter=true;
		sCols->Delimiter='\t';

		String s;
		if(bContainHeader)
		{
			for(int iCol=sRec.Left;iCol<=sRec.Right;iCol++)
			{
				sCols->Add(Grid->Cells[iCol][0]);
			}
			sLst->Add(sCols->DelimitedText);
		}
		//--------------------------------------------
		for(int iRow=sRec.Top;iRow<=sRec.Bottom;iRow++)
		{
			sCols->Clear();
			for(int iCol=sRec.Left;iCol<=sRec.Right;iCol++)
			{
				sCols->Add(Grid->Cells[iCol][iRow]);
			}
			sLst->Add(sCols->DelimitedText);
		}
		Clipboard()->AsText=sLst->Text;
	}
	__finally
	{
		delete sCols;
		delete sLst;
	}
}



위 함수에서 FixedRow인 Column-Header는 Grid에서 Select되지 않기 때문에..
bContainHeader 라는 파라메터를 이용해 포함할것인지 말것인지 결정해 주고 있다.


@ClipBoard의 TabText를 Grid에 넣기
이번엔 Clipboard의 내용을 Grid에  넣게를 해보자

//---------------------------------------------------------------------------
// Tab-Text로 된 Clipboard의 Text를 Grid에 넣어준다.
//---------------------------------------------------------------------------
void __fastcall PasteGridFromClipbrd(TStringGrid *Grid)
{
	TGridRect sRec=Grid->Selection;
	TStringList *sLst=new TStringList;
	TStringList *sCols=new TStringList;

	try
	{
		sLst->Text=Clipboard()->AsText;
		sCols->StrictDelimiter=true;
		sCols->Delimiter='\t';

		for(int r=0 ; r < sLst->Count ; r++ )
		{
			sCols->DelimitedText=sLst->Strings[r];
			if((sRec.Top+r) >= Grid->RowCount )break;
			for(int c=0 ; c < sCols->Count ; c++ )
			{
				if((sRec.Left+c) >= Grid->ColCount )break;
				Grid->Cells[sRec.Left+c][sRec.Top+r] = sCols->Strings[c];
			}
		}
	}
	__finally
	{
		delete sLst;
		delete sCols;
	}
}




@사용방법은?
위 엑셀연동함수를 사용하는 방법은?
대충 당음과 같이하면 될듯한다.

// ---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
	// ---------------------------
	// Clipboard복사 기능
	if (Shift.Contains(ssCtrl))
	{
		if(Key == 'C' || Key == 'c')
		{
			CopyGridToClipbrd(StringGrid1,false);
		}
		else if(Key == 'V' || Key == 'v')
		{
			PasteGridFromClipbrd(StringGrid1);
		}
	}
}



델파이 버젼 코드는 생략..

주의
StringList에서 StrictDelimiter 프로퍼티는
Delphi7 이하 버젼에는 없는 기능이다.


그럼...
장성호 [nasilso]   2012-06-20 10:40 X
엥...
오늘 검색해보니 똑같은 내용을  이미 팁게시판에 제가 올려뒀었네요 쩝쩝
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=1073

+ -

관련 글 리스트
1093 [Controls] TSV (Tab Separated Value) 와 StringGrid 그리고 엑셀 연동 장성호 10186 2012/06/15
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.