//********************************************************************************************
/**
 * @file		xls2csv.cpp
 * @brief		エクセルファイルをcsvに展開
 *
 *	このファイルの詳細説明
 *
 * @date		2011/12/12	takedan	新規作成.
 */
//********************************************************************************************

#define	SW_MODULE_XLS2CSV						///< この機能を切り離したい時はコメントアウト.
#ifdef	SW_MODULE_XLS2CSV

#ifndef _STOOLS_H
#include <system\win32\dde.h>
#endif


//********************************************************************************************
/**
 * @class		XLS2CSV
 * @brief		エクセルファイルをcsvに展開スクリプトコマンドクラス.
 */
//********************************************************************************************
class XLS2CSV
{
	StDDEState	m_stDDEState;
	
	HINSTANCE	m_hInst;
	
	Bool		m_bPrinted;
	BOOL		m_bInitialized;
	BOOL		m_bImplemented;
	BOOL		m_bFullInit;
	
	void		Initialize();
	
public:
	static HWND				s_hFindWhd;
	static BOOL CALLBACK	EnumWindowsProc( HWND _hWnd , LPARAM _lp );

	virtual int		Func( LPCTSTR _sParamString );
	virtual void	Quit( BOOL _bExit );
	
	XLS2CSV();
	virtual ~XLS2CSV();
	
};

//********************************************************************************************
/**
 * @brief		エクセルファイルをcsvに展開コンストラクタ.
 */
//********************************************************************************************
XLS2CSV::XLS2CSV()
	: m_bFullInit( FALSE )
	, m_bInitialized( FALSE )
	, m_bImplemented( FALSE )
{
	
}

//********************************************************************************************
/**
 * @brief		エクセルファイルをcsvに展開デストラクタ.
 */
//********************************************************************************************
XLS2CSV::~XLS2CSV()
{
	
}


//==============================================================================================================================================
/**
	初期化と開放.
		1ファイルに1つの処理でコンプリートするような場合は修正する必要ありません
		注釈となっている Message_printf を有効にして sample.swb を実行すると動きがよく分かると思います。
*/
//==============================================================================================================================================

HWND	XLS2CSV::s_hFindWhd = NULL;

//********************************************************************************************
/**
 * @brief		エクセルファイルをcsvに展開スクリプトコマンドの初期化.
 *				(特に必要ないなら変更の必要なし)
 *
 * @return		なし (none)
 */
//********************************************************************************************
void	XLS2CSV::Initialize()
{
	if( m_bInitialized == TRUE )	return;
	m_bInitialized = TRUE;	//	初期済みフラグ
	
	if( m_bFullInit == FALSE )
	{
		m_bFullInit = TRUE;
		//	全体を通して一度しか行わない初期化
		
		//Message_printf( TEXT("全体の初期化") );
		
	}
	
	//	初期化処理
	//	１つのバッチに同じスクリプトが２度指定されていたならここには２度来る
	//Message_printf( TEXT("初期化") );
	
}

//********************************************************************************************
/**
 * @brief		エクセルファイルをcsvに展開スクリプトコマンドの終了.
 *				(特に必要ないなら変更の必要なし)
 *
 * @param[in]	BOOL	_bExit	.
 *
 * @return		なし (none)
 */
//********************************************************************************************
void	XLS2CSV::Quit(BOOL _bExit)
{
	//	ここにはスクリプトを使っていなくても来るので注意
	
	if( m_bImplemented == FALSE )	return;		///<変換処理が実行されていないなら帰還.
	m_bImplemented = FALSE;
	m_bInitialized = FALSE;
	
	///	終了処理.
	//Message_printf( TEXT("終了") );
	
	if( _bExit == TRUE )
	{
		//	次のスクリプトは存在しない、完全な終了
		//	１つのバッチに同じスクリプトに別パラメータを渡しての処理で
		//	逐一結果を出さず、全体で統合して結果を出したい場合などはここで
		
		//Message_printf( TEXT("全体の終了") );
	}
	
}


//********************************************************************************************
/**
 * @brief		エクセルのウィンドウハンドルを得る.
 * @author		N.Takeda
 * @date		2011/11/28(月) 17:00:26
 *
 * @param[in]		HWND	_hWnd	.
 * @param[in,out]	LPARAM	_lp		.
 *
 * @return		BOOL CALLBACK	TRUE:成 / FALSE:否
 */
//********************************************************************************************
BOOL CALLBACK XLS2CSV::EnumWindowsProc( HWND _hWnd , LPARAM _lp )
{
	TCHAR	strWindowText[1024];
	
	if( (HINSTANCE)_lp != (HINSTANCE)GetWindowLong( _hWnd, GWL_HINSTANCE) )
	{
		GetWindowText(_hWnd , strWindowText , 1024);
		if (strWindowText[0] == 0) return TRUE;
		
		if( NULL != STRING_str( strWindowText, TEXT("Microsoft"), 1024, NULL ) )
			if( NULL != STRING_str( strWindowText, TEXT("Excel"), 1024, NULL ) )
			{
				s_hFindWhd = _hWnd;
				return FALSE;
			}
		return TRUE;
	}
	s_hFindWhd = _hWnd;
	return FALSE;
}





//==============================================================================================================================================
//	変換処理部分
//==============================================================================================================================================

#define	XLS2CSV_OUTAREA		2	///< 変換後の容量は仮に元の倍取っている　内容によって変更して下さい.
#define	XLS2CSV_RANGE				///< このdefineを有効にすると範囲限定機能が有効になる.

//********************************************************************************************
/**
 * @brief	エクセルファイルをcsvに展開変換フィルターサンプル　機能:無変換
 *			テキストデータを取り扱うサンプル.
 *			関数内は patol.lib を使用したサンプルになっているが、中身は完全に別物に変えても問題ありません.
 *
 *			
 *
 * @param[in]	LPCTSTR	_sParamString	引数文字列  ターゲットファイル名 + スクリプトで指定する引数.
 *
 * @return		int	TRUE:成 / FALSE:否(デフォルト)
 */
//********************************************************************************************
int		XLS2CSV::Func( LPCTSTR _sParamString )
{
	CSwbParam	cParam( _sParamString );							///< パラメータ処理.
	
	int		ii, jj, iSx, iSy, iEx, iEy;
	LPCTSTR	szFileName, sRange;
	LPTSTR	pPtr;
	TCHAR	cTemp[ 256 ];
	
	#define	REBUFF_SIZE	(4*1024)
	TCHAR	sReBuf[ REBUFF_SIZE ];
	
	
	/// 引数の取り出し.
	/**
	 * ターゲットファイル (GetString(0)としても同じ).
	 * swb ファイルでは指定しない、システムで付加される引数.
	 */
	szFileName = cParam.GetPath();
	sRange   = cParam.GetString( 1 );
	
	
	iSx = iSy = iEx = iEy = -1;
	
	/// 機能の初期化.
	Initialize();
	
	if( sRange )
	{
		if( STRING_str( sRange, TEXT("-r") ) == sRange )
		{
			pPtr = (LPTSTR)(sRange + 2);
			
			if( *pPtr >= 'A' && *pPtr <= 'Z' )
			{
				jj = 0;
				while( 1 )
				{
					if( 0>iSx )
					{
						if( *pPtr >= 'A' && *pPtr <= 'Z' )
						{
							jj *= ('Z'-'A');
							jj += (*pPtr) - 'A' + 1;
							pPtr++;
						}else{
							iSx = jj;
							jj = 0;
						}
					}
					else if( 0>iSy )
					{
						if( *pPtr >= '0' && *pPtr <= '9' )
						{
							jj *= 10;
							jj += (*pPtr) - '0';
							pPtr++;
						}else{
							iSy = jj;
							jj = 0;
						}
					}
					else if( 0>iEx )
					{
						if( *pPtr >= 'A' && *pPtr <= 'Z' )
						{
							jj *= ('Z'-'A');
							jj += (*pPtr) - 'A' + 1;
							pPtr++;
						}else{
							iEx = jj;
							jj = 0;
						}
					}
					else if( 0>iEy )
					{
						if( *pPtr >= '0' && *pPtr <= '9' )
						{
							jj *= 10;
							jj += (*pPtr) - '0';
							pPtr++;
						}
						else{
							iEy = jj;
							break;
						}
					}
				}
				
			}else{
				Message_printf( TEXT("未対応") );
			}
		}
	}else{
		iSx = iSy = 0;
		iEx = 256;
		iEy = 4096;
	}
	
	if( 0>iSx || 0>iSy || 0>=iEx || 0>=iEy )	return TRUE;
	
	/// Excelファイルを開く.
	m_hInst = ShellExecute( NULL, TEXT("open"), szFileName, NULL, NULL, SW_MINIMIZE );
	
	_stZero( StDDEState, &m_stDDEState );
	
	
	TCHAR	cPath[ T_MAXPATH], cDrive[T_MAXDRIVE],cDir[T_MAXDIR],cName[T_MAXNAME];
	TCHAR	cSheetNames[ 256 ];
	Int32	iSheetEntry = DDEXL_GetSheets( szFileName, cSheetNames, 256 );
	pPtr = cSheetNames;
	
	
	if( !m_bPrinted )
	{
		Message_printf( TEXT("Cell(%d,%d)-(%d,%d)"), iSx, iSy, iEx, iEy );
		m_bPrinted = TRUE;
	}
	
	for( Int32 iTab=0 ; iTab<iSheetEntry ; iTab++ )
	{
		DDEXL_Start( &m_stDDEState, szFileName, pPtr );
		
		FILE_split( szFileName, cDrive, cDir, cName, NULL );
		STRING_cat( cName, pPtr );
		FILE_merge( cPath, cDrive, cDir, cName, TEXT(".csv") );
		
		/// セル走査.
		for( jj=iSx ; jj<=iEx ; jj++ )
		{
			for( ii=iSy ; ii<=iEy ; ii++ )
			{
				if( 0 > DDEXL_GetData( &m_stDDEState, ii, jj, sReBuf, REBUFF_SIZE ) )
				{
					Message_printf( TEXT("(%s)DDEが開始されていません"), szFileName );
					break;
				}
				if( 2 < STRING_len(sReBuf) )	///< 改行のみの場合も弾くため２文字以上.
				{
//					SetLine( ii );
					STRING_printf( cTemp, 256, TEXT("[%s]%s"), szFileName, pPtr );
					/// 前後の " 、末端の制御記号を除いてチェック.
					while( sReBuf[STRING_len(sReBuf)-1] == '\"' || sReBuf[STRING_len(sReBuf)-1] <= ' ' )
					{
						sReBuf[STRING_len(sReBuf)-1] = '\0';
					}
					FILE_stream( cPath, sReBuf );
//					check_string( cTemp, sReBuf + (sReBuf[0]=='\"'), STRING_len(sReBuf) - (sReBuf[0]=='\"') );
				}
			}
		}
		DDEXL_End( &m_stDDEState );
		
		pPtr += STRING_len( pPtr ) + 1;
	}
	
	
	EnumWindows( EnumWindowsProc , (LPARAM)m_hInst );
	if( s_hFindWhd )	PostMessage( s_hFindWhd, WM_CLOSE, 0, 0 );
	
	return TRUE;
}


XLS2CSV	*pC_xls2csv = NULL;

#endif	// SW_MODULE_XLS2CSV
