下载: http://XiaoJinTa.com/download/integrate_stock.zip
//---------------------------------------------------------------------------
// C++ Builder XE
// 刘涛 136,1308,6264 30234923@qq.com QQ: 30234923 MSN: newtower@hotmail.com http://XiaoJinTa.com
#include <math.h>
#include <IniFiles.hpp>
#include <vcl.h>
#pragma hdrstop
#include "Unit5.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm5 *Form5;
#define OPG OlePropertyGet
#define OPS OlePropertySet
#define OFN OleFunction
#define OPR OleProcedure
#define PR Procedure
#define NTTEST 1 // 测试专用代码
#define ntTEST NTTEST
#define ntMaxAllocMemorySize 1024*1024*3
#define NTSTR_ALL "--- 全部 ---"
#define alert( Str ) ntShowMessage( Str )
#define ntShowMsg( Str ) ntShowMessage( Str )
#define ntShowMessage(Str) Application->MessageBox( (String()+"/n"+(Str)+"/n").c_str(), String("信息和提示").c_str(), MB_OK)
#define ntTest() ntShowMessage(" 测试! ")
#define ntProcMsg() Application->ProcessMessages()
// func: A {
//保存文本到文件中
void ntSaveToFile( String FileName , String Content )
{
if( !DirectoryExists( ExtractFilePath(FileName) ) )
ForceDirectories( ExtractFilePath(FileName) );
/* 保留
TStringList *SL = new TStringList();
try{
SL->Text = Content;
SL->SaveToFile(FileName); //有问题,会改变一些内容的[/n] 0A -> 0D 0A
}__finally{
if( NULL != SL ) delete SL;
}
*/
// SL->SaveToFile(FileName); //有问题,会改变一些内容的[/n] 0A -> 0D 0A
TFileStream *NewFile = NULL;
try
{
NewFile = new TFileStream( FileName, fmCreate );
AnsiString s = Content;
NewFile->WriteBuffer( s.c_str(), s.Length() );
}
__finally
{
delete NewFile;
}
}// end ntSaveToFile(...)
/*
[Form]
Top=185
Left=280
Caption=Default Caption
InitMax=0
*/
//读ini
String ntIniRead( const String iniFileName ,
const String Key ,
const String Item )
{
String r = "";
TIniFile *ini = NULL;
try{
ini = new TIniFile( iniFileName );
r = ini->ReadString( Key, Item, ""); //第3个参数是如果没有取到的默认值
//}catch(...){
// ntShowMessage(String()
// +"读出ini文件: "+iniFileName+ " 时出错! /n"
// +"Key = " + Key + "/n" + "Item = " + Item+ "/n" );
}__finally{
if( NULL != ini ) delete ini;
}
//
return r;
}// end ntIniRead
//写ini 如果文件不存在, 会自动创建
void ntIniWrite( const String iniFileName ,
const String Key ,
const String Item ,
const String Value )
{
TIniFile *ini = NULL;
try{
try{
ini = new TIniFile( iniFileName );
ini->WriteString( Key, Item, Value );
//ini->UpdateFile();
}catch(...){
ntShowMessage(String()
+"写ini文件: "+iniFileName+ " 时出错! /n"
+"Key = " + Key + "/n" + "Item = " + Item+ "/n"
+"Value= " + Value + "/n"
);
}
}
__finally
{
if( NULL != ini ) delete ini;
}
}// end ntIniWrite
/*
// 计算时间差, 推荐
TntElapse ntElapse;
// ntElapse.Begin(); // 可以不用
......
ntElapse.End();
Memo2->Lines->Add("运行时长: "+ ntElapse.TimeStringValue );
// StringValue , DateTimeStringValue, TimeStringValue, doubleValue , intValue
*/
// 计算运行时长
class TntElapse{
public:
TDateTime d0;
TDateTime d1;
double doubleValue;
int intValue;
String StringValue; // 格式化的 FormatFloat("#,##0.000", d) + " 秒 ";
String TimeStringValue; // 格式化的 hh:nn:ss.zzz
String DateTimeStringValue; // 格式化的 yyyy-mm-dd hh:nn:ss.zzz
TntElapse()
{
//p = new TIdHTTP( Application ); // 有错误,不可以用
d0 = Now();
d1 = Now();
doubleValue = 0.0;
intValue = 0;
StringValue = "";
}
void Begin()
{
d0 = Now();
}
void End()
{
d1 = Now();
//两个时间相差的秒数,是绝对值
//int x = int( (b.Val - a.Val)*60*60*24 + 0.5 ); // 四舍五入
double x = double(d1 - d0)*60*60*24;
x = fabs(x);
doubleValue = x;
intValue = (int)x;
StringValue = FormatFloat("#,##0.000", x); // 秒,double
DateTimeStringValue = FormatDateTime(
"yyyy-mm-dd hh:nn:ss.zzz", (d1 - d0) );
TimeStringValue = FormatDateTime(
"hh:nn:ss.zzz", (d1 - d0) );
}
~TntElapse()
{
// if( p ) { delete p; p=NULL; }
}
};
// stl: class TntStrHashtable // Hashtable 用 TntStrHashtable 代替
// Vector 可以用 TList来代替, 但效率不高, 最好用stl实现
// map中的键值必须是唯一的
// ar[43] = "overripe",map还可以ar["banana"]="overripe"
// // 可以通过ntMapSS[i]的方法来遍历
/*
TntStrHashtable nt;
nt.put("1","aa");
nt.put("2","bb");
nt.put("3","cc");
//Memo2->Lines->Add( String()+ "["+ nt.get(3)+"]" ); // cc
//Memo2->Lines->Add( String()+ "["+ nt.get(4)+"]" ); // ""
// 遍历的操作
TntMapStrStr::iterator pfind = NULL; // nt.begin();
for( pfind = nt.ntMapSS.begin(); pfind != nt.ntMapSS.end();pfind++)
{
Memo2->Lines->Add( String()+ "key = ["+ pfind->first +"]" );
Memo2->Lines->Add( String()+ "val = ["+ pfind->second +"]" );
}
*/
/*
注意需要包含下面才能编译正常
#include <vector>
#include <list>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
*/
#include <map>
//
typedef std::map<String, String> TntMapStrStr; // <TEdit*,String>
class TntStrHashtable{
public:
TntMapStrStr ntMapSS;
public:
TntStrHashtable(void)
{}
bool find(String _key)
{
TntMapStrStr::iterator theIterator = ntMapSS.find( _key );
if( theIterator != ntMapSS.end() ) //return (*theIterator).second; //return TEdit*
return true;
//else // 没有找到
// return false;
return false;
}
bool contains(String _key)
{ return find(_key); }
String get(String _key)
{
String r="";
TntMapStrStr::iterator theIterator = ntMapSS.find( _key );
if( theIterator != ntMapSS.end() ) //return (*theIterator).second; //return TEdit*
r = (*theIterator).second;
else // 没有找到
r = "";
return r;
//return ntMapSS[_key]; // 这个有错误,不可以用
}
String get(int pos) // 起始为1, 超越范围返回""
{
return ntMapSS[pos];
}
//String getKey(int pos)
//{
// return "";
//}
void put(String _key, String _value)
{
/* // 否则有如下的错误
TntStrHashtable nt;
nt.put("t1.f1","1");
nt.put("t1.f1","2");
ntShowMsg( nt.get("t1.f1") + "---" ); // 1---
*/
if( _key.Length() <=0 )
return;
if( _value.Length() <=0 )
{
remove(_key);
return;
}
if( contains(_key) )
remove(_key);
ntMapSS.insert( TntMapStrStr::value_type( _key, _value) );
}
void remove(String _key)
{
ntMapSS.erase( _key );
}
int size()
{
return ntMapSS.size();
}
void clear()
{
ntMapSS.clear();
}
~TntStrHashtable(void)
{
ntMapSS.clear();
}
}; //end TntStrHashtable
String ntNow() // 同 ntNow_full
{ return FormatDateTime("yyyy-mm-dd hh:nn:ss.zzz",Now()); }
String ntNow_full()
{ return FormatDateTime("yyyy-mm-dd hh:nn:ss.zzz",Now()); }
String ntNow_sec()
{ return FormatDateTime("yyyy-mm-dd hh:nn:ss",Now()); }
String ntNow_day()
{ return FormatDateTime("yyyy-mm-dd",Now()); }
// 忽略大小写的替换
String ntStringReplace( const String S, const String OldPattern, const String NewPattern )
{
String r = StringReplace( S, OldPattern, NewPattern
, TReplaceFlags() << rfReplaceAll << rfIgnoreCase );
return r;
}
// c++ bcb中以1开始 index,count; java以0开始 begin,end
/*
substring 为起止位
<% out.println("<!-- "+ (new String("123456")).substring(0,3) +" -->"); %>
<% out.println("<!-- "+ (new String("123456")).substring(1,3) +" -->"); %>
结果为"123" , "23"
ntSubString 模拟java中的
*/
String ntSubString(const String _s, int _begin, int _end)
{
int len = _s.Length();
if( 0 == len )
return "";
if( _end < _begin || _begin < 0 || _end < 0 )
return "";
int _b = _begin + 1; // 123456, 34 java: 2,4 bcb: 3,2
int _e = _end;
if( _end > len )
_e = len;
_e = _e - _begin;
return _s.SubString( _b, _e );
}
// extern PACKAGE char * __fastcall StrPos(const char * Str1, const char * Str2);
// -1表示没有,0表示第一个, 最后一个出现_sub的位置
// ntLastStrPos
int ntLastIndexOf(const String _s, const String _sub)
{
int r = -1;
int sLen = _s.Length();
int subLen = _sub.Length();
// 极限情况判断: begin
if( subLen > sLen )
return r;
if( subLen == sLen )
{
if( CompareStr( _s, _sub ) == 0 )
return 0;
else
return r;
}
// 极限情况判断: end
// 现在已经保证是正常情况,sLen > subLen
// 123456789
// 678
// 从后往前循环查找
for( int i=sLen - subLen + 1; i >=1; i-- )
{
// 对比此位置的字符串情况
bool isOK = true;
// 如果不是所有字符都匹配,就为false
for(int j=1; j<= subLen ; j++ )
{
if( _s[i+j-1] != _sub[j] )
{
isOK = false;
break;
}
}
if( isOK ) // 如果此位置是
{
r = i - 1;
break;
}
} // end for i
return r;
} // end ntLastIndexOf
// 和 ntLastIndexOf 一样,不过是从 1 开始
int ntLastPos(const String _s, const String _sub)
{
return ntLastIndexOf( _s, _sub ) + 1;
}
// 2010-10-16
// 取出 abc.txt 中 abc
String ntExtractFilePrefix( String _s )
{
String s = _s;
s = ExtractFileName( s );
s = ntSubString( s, 0, ntLastIndexOf(s, ".") );
return s;
}
class TntStrings{
public:
TStrings *p;
TStringList *pL; // pL 其实就是 p, 避免以后的类型转化
public:
TntStrings()
{
p = new TStringList();
pL = (TStringList *)p;
}
~TntStrings(void)
{
if( p ) delete p;
p = NULL;
pL = NULL;
}
}; //end TntStrings
//列出某个目录下全部的目录的列表, "C://1/nC://1//A", 用"/n"分隔
// ntGetDirectories("e://1","[","]"); prefix suffix是前后加入的字符串
String ntGetDirectories(
const String Dir
,const String prefix
,const String suffix
)
{
//
String Str;
if( Dir[Dir.Length()] != '//' )
{ Str = Dir + "//"; }
else
{ Str = Dir; }
String result="";
if( !DirectoryExists( Str ) )
{ return result; }
else
result = result + prefix + Str + suffix ;
TSearchRec sr;
int iAttributes = 0;
iAttributes = faDirectory ;
if( FindFirst( Str + "*.*", iAttributes, sr) == 0 )
{
do
{
//ShowMessage( "'"+sr.Name +"' = "+ sr.Name.Length() +"/n"+ sr.Attr );
if( sr.Attr == faDirectory
&&
sr.Name.Trim() !="/."
&&
sr.Name.Trim() !="/./." )
{
result = result + "/n"
+ntGetDirectories(Str+sr.Name,prefix,suffix); // Str是目录
}
} while (FindNext(sr) == 0);
FindClose(sr);
}
return result;
}
//列出某个目录下全部的目录的列表, "C://1/nC://1//A", 用"/n"分隔
// ntGetDirectories("e://1")
String ntGetDirectories( const String Dir )
{
return ntGetDirectories(Dir,"","");
// return ntGetDirectories( Dir, String(""), String("") );
}
//---------------------------------------------------------------------------
//列出某个目录下全部的文件的列表, "C://aa.txt/nC://bb.txt", 用"/n"分隔
String ntGetFiles( const String Dir )
{
//
String Str;
if( Dir[Dir.Length()] != '//' )
{ Str = Dir + "//"; }
else
{ Str = Dir; }
String result="";
Str = ExpandFileName( Str );
if( !DirectoryExists( Str ) )
{ return result; }
TSearchRec sr;
int iAttributes = 0;
iAttributes = faAnyFile ;
if( FindFirst( Str + "*.*", iAttributes, sr) == 0 )
{
do
{
//ShowMessage( "'"+sr.Name +"' = "+ sr.Name.Length() +"/n"+ sr.Attr );
if(
sr.Attr != faDirectory
&&
sr.Name.Trim() !="/."
&&
sr.Name.Trim() !="/./." )
{
result = result + sr.Name + "/n" ; // Str是目录
}
} while (FindNext(sr) == 0);
FindClose(sr);
}
return result.Trim();
}
//end ntGetFiles( ... )
//列出某个目录下的文件(包括子目录)的列表, "C://aa.txt/nC://bb.txt", 用"/n"分隔
String ntGetFiles_All( const String Dir )
{
TStringList *p = NULL;
TStringList *x = NULL;
String r = "";
try
{
p = new TStringList();
x = new TStringList();
//
p->Text = ntGetDirectories( Dir );
for(int i=0;i<p->Count;i++)
{
x->Text = ntGetFiles(p->Strings[i]);
for(int j=0;j<x->Count;j++)
{
r = r + p->Strings[i] + x->Strings[j] + "/n";
}
}
//
}
__finally
{
if( p )
delete p;
if( x )
delete x;
}
return r.Trim();
}// end ntGetFiles_All(.)
// func: Z }
// filename:
AnsiString fnDir = GetCurrentDir() + "//行情数据//";
AnsiString fnDir_output = GetCurrentDir() + "//行情数据_整合输出//";
AnsiString fn_ini = GetCurrentDir() + "//Excel.ini";
//---------------------------------------------------------------------------
__fastcall TForm5::TForm5(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
TForm5::msg( String s)
{
if( s == "" )
Memo1->Lines->Add( "" );
else
Memo1->Lines->Add( String() + ntNow() + ": " + s );
}
//---------------------------------------------------------------------------
void __fastcall TForm5::Button1Click(TObject *Sender)
{
Variant ex, wb, sh1, tmp1, sh2;
String s路径 = GetCurrentDir();
// ShowMessage( s路径 );
//赋值内容
AnsiString s = "hello!呵呵";
//文件路径和保存名称
AnsiString fn = GetCurrentDir() + "//test.xls";
//判断文件是否存在
if( FileExists( fn ) )
{
ShowMessage("exist test file");
// 询问是否删除
if( MessageDlg("文件已经存在,是否删除?",
mtWarning, TMsgDlgButtons() << mbOK << mbCancel, 0) == mrOk
)
DeleteFile( fn );
else
{ ShowMessage("放弃操作"); return; }
}
try {
// 建立excel连接
ex= Variant::CreateObject("Excel.Application");
ex.OPS("Visible", false);
wb = ex.OPG("Workbooks");
// 创建一个新的excel工作本(文件)
wb.Exec( PR("Add") );
wb = ex.OPG("ActiveWorkbook");
// 本文转自 C++Builder研究 - http://www.ccrun.com/article.asp?i=543&d=667o3e
// 显示存在的sheet数目
int count = wb.OPG("sheets").OPG("count");
// ShowMessage( IntToStr(count) + "个表");
// 添加一个Sheet,命名为test
sh2 = wb.OPG("sheets", count);
wb.OPG("sheets").OPR("Add", tmp1.NoParam(), sh2);
sh1 = wb.OPG("ActiveSheet");
// Rename
sh1.OPS("Name","test");
// 给单元1,2赋值
sh1.OPG("Cells")
.OPG("Item",(Variant)1,(Variant)2)
.OPS("Value",
s.c_str()
);
// .Exec(PropertySet("Value")<< s.c_str());
//以上两种方式都可以
//选择第一张sheet
int sheetnum=1;
sh1 = wb.OPG("sheets", sheetnum);
//选择名字为sheet2的表单
AnsiString shname = "sheet2";
// ShowMessage( 2 );
sh1 = wb.OPG("sheets", shname.c_str() );
//关闭警告提示
wb.OPG("Application").OPS("DisplayAlerts",false);
//删除选定表单
sh1.OFN("Delete");
//打开警告提示
wb.OPG("Application").OPS("DisplayAlerts",false);
//保存文件,两种方式都可以
//wb.Exec(PR("SaveAs")<<fn);
wb.OPR("SaveAs",fn.c_str());
} __finally {
//结束退出
wb.OPR("Close");
ex.OFN("Quit");
//结束,如果没有如下代码,EXCEL线程直到应用程序退出才结束。
ex = Unassigned;
wb = Unassigned;
sh1 = Unassigned;
tmp1 = Unassigned;
sh2 = Unassigned;
ShowMessage("Well Done boy!");
}
}
//---------------------------------------------------------------------------
void __fastcall TForm5::Button2Click(TObject *Sender)
{
// 读取测试
Variant ex, wb, sh1;
AnsiString fn = GetCurrentDir() + "//0921.xls"; // ok
// AnsiString fn = GetCurrentDir() + "//0928.bin.xls"; // ok, 文件名大小写无所谓
// AnsiString fn = GetCurrentDir() + "//0928.txt.xls"; // ok, 文件名大小写无所谓
// 读取 txt 格式 和 bin 格式的 xls 均可
try {
ex = Variant::CreateObject("Excel.Application");
// ex.OPS("Visible", false);
ex.OPS("Visible", true);
ex.OPG("WorkBooks").OPR("Open", fn.c_str() );
// 获取 工作簿
wb = ex.OPG("ActiveWorkBook");
// 获取 表单
// sh1 = wb.OPG("ActiveSheet");
sh1 = wb.OPG("Sheets", 1); // 获取第一个Sheet, 1开始
// 表单数
int SheetCount = wb.OPG("Sheets").OPG("Count");
String s = (String()+ "SheetCount = [" + SheetCount + "]" );
msg( s );
// 行列数
int i行数 = sh1.OPG("UsedRange").OPG("Rows").OPG("Count"); //行数
int i列数 = sh1.OPG("UsedRange").OPG("Columns").OPG("Count"); //列数
s = String()+" i行数 = "+ i行数 +" ";
msg( s );
s = String()+" i列数 = "+ i列数 +" ";
msg( s );
// 获取值, 3 行, 1 列, 3A
s = sh1.OPG("Cells", 3, 1).OPG("Value");
s = String()+ " * cell value: [" + s + "]";
msg( s );
// 取第一行所有值, 注意有时 i列数 不可靠, 所以要多取几列, 超出范围不要紧
for(int j=1; j<= i列数 + 3 ; j++)
{
s = sh1.OPG("Cells", 1, j).OPG("Value");
s = String()+ "cell(1, "+ j +") value: [" + s + "]";
msg( s );
}
// 写值
for(int i=1; i<=10; i++)
for(int j=1; j<=10; j++)
{
// sh1.OPG("Cells",i,j).OPS("Value", i*100+j);
}
// wb.OPR("Save");
} __finally {
wb.OPR("Close");
ex.OFN("Quit");
ex = Unassigned;
wb = Unassigned;
sh1= Unassigned;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm5::Button3Click(TObject *Sender)
{
// test3
// 创建文件测试
Variant ex, wb, sh1;
AnsiString fn = GetCurrentDir() + "//test3.xls";
if( FileExists( fn ) )
DeleteFile( fn );
try {
ex = Variant::CreateObject("Excel.Application");
// ex.OPS("Visible", false);
ex.OPS("Visible", true);
// ex.OPG("WorkBooks").OPR("Open", fn.c_str() );
wb = ex.OPG("Workbooks");
wb.Exec( PR("Add") );
wb = ex.OPG("ActiveWorkBook");
// sh1 = wb.OPG("ActiveSheet");
sh1 = wb.OPG("Sheets", 1); // 获取第一个Sheet, 1开始
// 获取值, 3 行 4 列 3D
// Edit1->Text = sh1.OPG("Cells",3,4).OPG("Value");
// 写值
for(int i=1; i<=10; i++)
for(int j=1; j<=10; j++)
{
sh1.OPG("Cells",i,j).OPS("Value", i*100+j);
sh1.OPG("Cells",i,j).OPG("Font").OPS("Color", RGB(150, 150, 150) ); // 颜色
sh1.OPG("Cells",1,1).OPG("Font").OPS("Bold", true ); // 加粗
}
// wb.OPR("Save");
wb.OPR("SaveAs",fn.c_str());
} __finally {
wb.OPR("Close");
ex.OFN("Quit");
ex = Unassigned;
wb = Unassigned;
sh1= Unassigned;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm5::Button_clearMemoClick(TObject *Sender)
{
Memo1->Lines->Text = "";
}
//---------------------------------------------------------------------------
void __fastcall TForm5::FormCreate(TObject *Sender)
{
Edit_fnDir->Text = fnDir;
Edit_fld->Text = "活跃度";
String s = "";
s = ntIniRead(fn_ini, "XiaoJinTa.com->Excel_股票数据整合", "XLS数据路径");
if( s != "" )
Edit_fnDir->Text = s;
s = ntIniRead(fn_ini, "XiaoJinTa.com->Excel_股票数据整合", "整合字段");
if( s != "" )
Edit_fld->Text = s;
}
//---------------------------------------------------------------------------
void __fastcall TForm5::FormClose(TObject *Sender, TCloseAction &Action)
{
ntIniWrite(fn_ini, "XiaoJinTa.com->Excel_股票数据整合", "XLS数据路径", Edit_fnDir->Text);
ntIniWrite(fn_ini, "XiaoJinTa.com->Excel_股票数据整合", "整合字段", Edit_fld->Text);
}
//---------------------------------------------------------------------------
void __fastcall TForm5::Button_closeClick(TObject *Sender)
{
//alert( sizeof(char) );
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm5::FormResize(TObject *Sender)
{
Memo1->Width = this->Width - ( 616 - 561 );
Memo1->Height = this->Height - ( 515 - 281 );
}
//---------------------------------------------------------------------------
void __fastcall TForm5::Button_exeClick(TObject *Sender)
{
// 计算时间差, 推荐
TntElapse ntElapse;
// ntElapse.Begin(); // 可以不用
((TButton *)Sender)->Enabled = 0;
int i_Label_loop = 0;
// 执行转化
if( Edit_fld->Text == "" )
{
alert("请指定 [整合字段]");
((TButton *)Sender)->Enabled = 1;
return;
}
// 输出目录
ForceDirectories( fnDir_output );
// 输出文件名
String fn_output = ""; // xls
String fn_output_txt = ""; // 过程信息输出
String s整合字段名_活跃度 = Edit_fld->Text;
// 除去 文件名不可以使用的字符:
{
String s = Edit_fld->Text.Trim(); // 整合字段名
s = ntStringReplace( s, "//", "");
s = ntStringReplace( s, "//", "");
s = ntStringReplace( s, ":", "");
s = ntStringReplace( s, "*", "");
s = ntStringReplace( s, "?", "");
s = ntStringReplace( s, "/"", "");
s = ntStringReplace( s, "<", "");
s = ntStringReplace( s, ">", "");
s = ntStringReplace( s, "|", "");
fn_output = fnDir_output + "股票数据整合"
+ "_" + s
+ "_" + FormatDateTime("yyyy.mm.dd_hh.nn.ss",Now())
+ "_" + ".xls";
fn_output_txt = fnDir_output + "股票数据整合"
+ "_" + s
+ "_" + FormatDateTime("yyyy.mm.dd_hh.nn.ss",Now())
+ "_" + ".txt";
}
// xls 文件列表的处理: A
fnDir = Edit_fnDir->Text;
String s文件列表 = ntGetFiles_All( fnDir );
// alert( s文件列表 );
TntStrings ssAll;
TntStrings ssFiles;
TntStrings ssFiles_date;
ssFiles.p->Text = s文件列表;
ssFiles.pL->Sort(); // 排序
// 消去 非xls文件
// alert( ssFiles.p->Strings[0] );
for(int i= ssFiles.p->Count -1; i >= 0; i-- )
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
String s = ssFiles.p->Strings[i]; // 0 start
// alert( String() + s.LowerCase().Pos(".xls") );
String s_low = s.LowerCase();
if( s_low.Pos(".xls") < 1 )
ssFiles.p->Delete( i );
} // for
// ssFiles 准备完毕, 包含了所有 xls , 并且升序排好
// 日期的处理
ssFiles_date.p->Text = ssFiles.p->Text;
for(int i= ssFiles_date.p->Count -1; i >= 0; i-- )
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
String s = ssFiles_date.p->Strings[i]; // 0 start
s = ntExtractFilePrefix( s );
if( s.Length() == 4 )
{
// s = FormatDateTime("yyyy",Now()) + "-" + s.SubString( 1, 2 ) + "-" + s.SubString( 3, 2 );
s = s.SubString( 1, 2 ) + "-" + s.SubString( 3, 2 );
}
else if( s.Length() == 8 )
s = s.SubString( 1, 4 ) + "-" + s.SubString( 5, 2 ) + "-" + s.SubString( 7, 2 );
ssFiles_date.p->Strings[i] = s;
} // for
// 日期处理完毕, ssFiles_date ok
// xls 文件列表的处理: Z
msg( "---- 输出时间: "+ ntNow() );
msg( "---- 输出文件: ["+ fn_output +"]" );
msg( "" );
msg( "---- xls文件列表" );
// Memo1->Lines->Text = Memo1->Lines->Text + s文件列表;
Memo1->Lines->AddStrings( ssFiles.p );
msg( "" );
/*
---- 文件列表
S:/BCB_Excel_股票数据整合_刘涛/Debug/Win32/行情数据/0921.xls
S:/BCB_Excel_股票数据整合_刘涛/Debug/Win32/行情数据/0927.XLS
S:/BCB_Excel_股票数据整合_刘涛/Debug/Win32/行情数据/0928.XLS
*/
msg( "---- 日期列表" );
Memo1->Lines->AddStrings( ssFiles_date.p );
msg( "" );
// 取得全部股票代码: A {
// 由于有的文件 股票代码不足, 所以要每个都取一遍, 然后集中起来
/*
TntStrHashtable nt;
nt.put("1","aa");
nt.put("2","bb");
nt.put("3","cc");
Memo1->Lines->Add( String()+ "["+ nt.get(3)+"]" ); // cc
Memo1->Lines->Add( String()+ "["+ nt.get(4)+"]" ); // ""
Memo1->Lines->Add( String()+ "["+ nt.get("3")+"]" ); // cc
Memo1->Lines->Add( String()+ "["+ nt.get("4")+"]" ); // ""
// 遍历的操作
TntMapStrStr::iterator pfind = NULL; // nt.begin();
for( pfind = nt.ntMapSS.begin(); pfind != nt.ntMapSS.end();pfind++)
{
Memo1->Lines->Add( String()+ "key = ["+ pfind->first +"]" );
Memo1->Lines->Add( String()+ "val = ["+ pfind->second +"]" );
}
*/
// 代码,名称
TntStrHashtable ht_Code;
msg( String()+ "---- 循环每个xls, 取得所有的 代码,名称 (共 "+ (ssFiles.p->Count) +" 个文件)" );
// 循环每个xls, 取得所有的 代码,名称: A {
// 也同时取到 全部 的字段 的内容, 用 TntStrings ssAll 存放
// ssAll 结构: 09-19 = ... ; 09-20 = ...
// 日期 ssFiles_date
// for(int i= ssFiles.p->Count -1; i >= 0; i-- )
for(int i_XLS= 0; i_XLS < ssFiles.p->Count; i_XLS++)
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
TntStrings ss; // 临时, 用来放字段的数据, 格式 [代码] = 字段值
String s日期 = ssFiles_date.p->Strings[i_XLS];
String fn_当前XLS = ssFiles.p->Strings[i_XLS]; // 0 start
// fn_当前XLS 是全路径文件名
// 读取
Variant ex, wb, sh1;
AnsiString fn = fn_当前XLS;
String s="";
try {
ex = Variant::CreateObject("Excel.Application");
// ex.OPS("Visible", false);
ex.OPS("Visible", false);
ex.OPG("WorkBooks").OPR("Open", fn.c_str() );
// 获取 工作簿
wb = ex.OPG("ActiveWorkBook");
// 获取 表单
// sh1 = wb.OPG("ActiveSheet");
sh1 = wb.OPG("Sheets", 1); // 获取第一个Sheet, 1开始
// 表单数
int SheetCount = wb.OPG("Sheets").OPG("Count");
// 行列数
int i行数 = sh1.OPG("UsedRange").OPG("Rows").OPG("Count"); //行数
int i列数 = sh1.OPG("UsedRange").OPG("Columns").OPG("Count"); //列数
// 获取值, 3 行, 1 列, 3A
// s = sh1.OPG("Cells", 3, 1).OPG("Value");
// 取第一行所有值, 注意有时 i列数 不可靠, 所以要多取几列, 超出范围不要紧
// 搜索 代码,名称
int pos_代码x = -1; // 所在行, 1 start
int pos_代码y = -1;
int pos_名称x = -1; // 所在行, 1 start
int pos_名称y = -1;
int pos_活跃度x = -1; // 所在行, 1 start
int pos_活跃度y = -1;
bool isBreak = false;
int i循环次数 = 0;
for(int i=1; i<= i行数 + 3; i++)
{
for(int j=1; j<= i列数 + 3; j++)
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
i循环次数 ++;
s = sh1.OPG("Cells", i, j).OPG("Value");
s = s.Trim();
if( s == "代码" )
{ pos_代码x = i; pos_代码y = j; isBreak = true; break; }
} // for
if( isBreak ) break;
} // for
// 代码 字段位置
msg( String()+"("+ (i_XLS +1) +"/"+ ssFiles.p->Count +")[代码]字段位置 = "+ pos_代码x +", " + pos_代码y + ", 循环次数=" + i循环次数 );
//
isBreak = false;
i循环次数 = 0;
for(int i=1; i<= i行数 + 3; i++)
{
for(int j=1; j<= i列数 + 3; j++)
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
i循环次数 ++;
s = sh1.OPG("Cells", i, j).OPG("Value");
s = s.Trim();
if( s == "名称" )
{ pos_名称x = i; pos_名称y = j; isBreak = true; break; }
} // for
if( isBreak ) break;
} // for
// 名称 字段位置
msg( String()+"("+ (i_XLS +1) +"/"+ ssFiles.p->Count +")[名称]字段位置 = "+ pos_名称x +", " + pos_名称y + ", 循环次数=" + i循环次数 );
//
isBreak = false;
i循环次数 = 0;
for(int i=1; i<= i行数 + 3; i++)
{
for(int j=1; j<= i列数 + 3; j++)
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
i循环次数 ++;
s = sh1.OPG("Cells", i, j).OPG("Value");
s = s.Trim();
if( s == s整合字段名_活跃度 ) // 活跃度
{ pos_活跃度x = i; pos_活跃度y = j; isBreak = true; break; }
} // for
if( isBreak ) break;
} // for
// 活跃度 字段位置
msg( String()+"("+ (i_XLS +1) +"/"+ ssFiles.p->Count +")["+ s整合字段名_活跃度 +"]字段位置 = "+ pos_活跃度x +", " + pos_活跃度y + ", 循环次数=" + i循环次数 );
/*
---- 循环每个xls, 取得所有的 代码,名称 (共 3 个文件)
(1/3)[代码]字段位置 = 1, 2, 循环次数=2
(1/3)[名称]字段位置 = 1, 3, 循环次数=3
(2/3)[代码]字段位置 = 1, 1, 循环次数=1
(2/3)[名称]字段位置 = 1, 2, 循环次数=2
(3/3)[代码]字段位置 = 1, 1, 循环次数=1
(3/3)[名称]字段位置 = 1, 2, 循环次数=2
*/
// 已经取得了 字段的位置
// 循环取得所有 [代码,名称] 字段 的值
// pos_代码x , pos_名称x
isBreak = false;
i循环次数 = 0;
for(int i= pos_代码x + 1; i<= i行数 + 3; i++)
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
i循环次数 ++;
String s代码 = sh1.OPG("Cells", i, pos_代码y ).OPG("Value");
String s名称 = sh1.OPG("Cells", i, pos_名称y ).OPG("Value");
String s活跃度 = sh1.OPG("Cells", i, pos_活跃度y ).OPG("Value");
s代码 = s代码.Trim();
s名称 = s名称.Trim();
while( s代码.Length() < 6 )
{ s代码 = String() + "0" + s代码; }
ht_Code.put( s代码, s名称 );
ss.p->Values[ s代码 ] = s活跃度;
} // for
// 名称 字段位置
msg( String()+"("+ (i_XLS +1) +"/"+ ssFiles.p->Count +") [代码,名称]获取完毕, size = "+ ht_Code.size() +", 循环次数=" + i循环次数 );
//
// ssAll 结构: 09-19 = ... ; 09-20 = ...
// 日期 ssFiles_date
ssAll.p->Values[ s日期 ] = ss.p->DelimitedText;
// ...
// 写值
/*
for(int i=1; i<=10; i++)
for(int j=1; j<=10; j++)
{
// sh1.OPG("Cells",i,j).OPS("Value", i*100+j);
}
*/
// wb.OPR("Save");
} __finally {
wb.OPR("Close");
ex.OFN("Quit");
ex = Unassigned;
wb = Unassigned;
sh1= Unassigned;
}
msg( "" );
} // for
// 循环每个xls, 取得所有的 代码,名称: Z }
// 生成排序好的 代码
TntStrings ss代码;
{ // sep
String s = "";
msg( "---- 代码,名称:" );
// 循环: A {
TntMapStrStr::iterator pfind = NULL; // ht_Code.begin();
int i1 = 1;
int icount = ht_Code.size();
for( pfind = ht_Code.ntMapSS.begin(); pfind != ht_Code.ntMapSS.end(); pfind++)
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
// Memo1->Lines->Add( String()+ "key = ["+ pfind->first +"]" );
// Memo1->Lines->Add( String()+ "val = ["+ pfind->second +"]" );
// Memo1->Lines->Add( String()+ "("+ i1 +"/"+ icount +") = ["+ pfind->first +"], ["+ pfind->second +"]" );
// ss代码.p->Text = s文件列表;
ss代码.p->Add( pfind->first );
i1 ++;
} // for
ss代码.pL->Sort(); // 排序
// 此时, ss代码 准备好了, 已经排序完毕
/*
---- 代码,名称:
(1/1922) = [000001], [深发展A]
(2/1922) = [000002], [万 科A]
(3/1922) = [000004], [ST国农]
*/
// 循环: Z }
/*
// 输出 代码,名称
icount = ss代码.p->Count;
for(int x=0; x< icount; x++ )
{
String k = ss代码.p->Strings[x];
String v = ht_Code.get( k );
msg( String()+ "("+ (x+1) +"/"+ icount +") = ["+ k +"], ["+ v +"]" );
} // for
*/
} // sep
// 取得全部股票代码: A }
// 创建文件: A {
msg("---- 开始写 xls ...");
Variant ex, wb, sh1;
// AnsiString fn = GetCurrentDir() + "//test3.xls";
AnsiString fn = fn_output;
if( FileExists( fn ) )
DeleteFile( fn );
try {
ex = Variant::CreateObject("Excel.Application");
ex.OPS("Visible", false);
//ex.OPS("Visible", true);
// ex.OPG("WorkBooks").OPR("Open", fn.c_str() );
wb = ex.OPG("Workbooks");
wb.Exec( PR("Add") );
wb = ex.OPG("ActiveWorkBook");
// sh1 = wb.OPG("ActiveSheet");
sh1 = wb.OPG("Sheets", 1); // 获取第一个Sheet, 1开始
// 获取值, 3 行 4 列 3D
// Edit1->Text = sh1.OPG("Cells",3,4).OPG("Value");
AnsiString sa = Edit_fld->Text; // [活跃度]
msg("---- 写 xls [字段],[日期], 即第一行 ...");
sh1.OPG("Cells",1,1).OPS("Value", sa.c_str() ); // [活跃度]
sh1.OPG("Cells",1,1).OPG("Font").OPS("size", 14 ); //大小
sh1.OPG("Cells",1,1).OPG("Font").OPS("Bold", true ); // 加粗
sh1.OPG("Cells",1,1).OPG("Font").OPS("Color", RGB(150, 150, 150) ); // 颜色
sh1.OPG("Cells",1,1).OPS("HorizontalAlignment", 3);//设置单元格中的文字距中
ex.OPG("Rows", 1).OPS("RowHeight", 20 ); // 设置行高
// 写日期: A {
int icount = ssFiles_date.p->Count;
// for(int i= ssFiles_date.p->Count -1; i >= 0; i-- )
for(int y=0; y< ssFiles_date.p->Count; y++ )
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
AnsiString s = ssFiles_date.p->Strings[y]; // 0 start
sh1.OPG("Cells", 1, y+3 ).OPS("NumberFormatLocal", "@"); // 设置为文本格式
// sh1.OPG("Cells", 1, y+3 ).OPS("HorizontalAlignment", 3);//设置单元格中的文字距中
sh1.OPG("Cells", 1, y+3).OPG("Font").OPS("size", 14 ); //大小
sh1.OPG("Cells", 1, y+3).OPG("Font").OPS("Bold", true ); // 加粗
sh1.OPG("Cells", 1, y+3).OPG("Font").OPS("Color", RGB(150, 150, 150) ); // 颜色
sh1.OPG("Cells", 1, y+3).OPS("HorizontalAlignment", 3);//设置单元格中的文字距中
sh1.OPG("Cells", 1, y+3 ).OPS("Value", s.c_str() ); // ok
} // for
// 写日期: Z }
msg("---- 写 xls: 输出 代码,名称 ...");
// 输出 代码,名称
icount = ss代码.p->Count;
for(int y=0; y< ssFiles_date.p->Count; y++ )
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
AnsiString _s日期 = ssFiles_date.p->Strings[y]; // 0 start
// sh1.OPG("Cells", x+2, y+3 ).OPS("NumberFormatLocal", "@"); // 设置为文本格式
// 通过 _s日期 , 取得 对应的 活跃度 集合, 放到 ss
TntStrings ss; // 临时, 用来放字段的数据, 格式 [代码] = 字段值
ss.p->DelimitedText = ssAll.p->Values[ _s日期 ];
ss.pL->Sort(); // 排序
for(int x=0; x< icount; x++ )
{
ntProcMsg(); i_Label_loop++; Label_loop->Caption = i_Label_loop;
AnsiString k = ss代码.p->Strings[x]; // 代码
AnsiString v = ht_Code.get( k ); // 名称
// msg( String()+ "("+ (x+1) +"/"+ icount +") = ["+ k +"], ["+ v +"]" );
sh1.OPG("Cells", x+2, 1).OPS("NumberFormatLocal", "@"); // 设置为文本格式
sh1.OPG("Cells", x+2, 1).OPS("HorizontalAlignment", 3);//设置单元格中的文字距中
// sh1.OPG("Cells", x+2, 1).OPS("Value", (AnsiString()+ "'" +k).c_str() ); // ok
sh1.OPG("Cells", x+2, 1).OPS("Value", k.c_str() ); // 代码
sh1.OPG("Cells", x+2, 2).OPS("Value", v.c_str() ); // 名称
// 输出 活跃度 值
// 通过集合, 得到 活跃度 值
AnsiString _s活跃度 = ss.p->Values[ k ];
sh1.OPG("Cells", x+2, y+3 ).OPS("Value", _s活跃度.c_str() ); // ok
//
} // for 行
} // for 活跃度
// 写值
/*
for(int i=1; i<=10; i++)
for(int j=1; j<=10; j++)
{
sh1.OPG("Cells",i,j).OPS("Value", i*100+j);
}
*/
// wb.OPR("Save");
wb.OPR("SaveAs",fn.c_str());
} __finally {
wb.OPR("Close");
ex.OFN("Quit");
ex = Unassigned;
wb = Unassigned;
sh1= Unassigned;
((TButton *)Sender)->Enabled = 1;
}
// 创建文件: Z }
// 计算时间差, 推荐
ntElapse.End();
// Memo2->Lines->Add("运行时长: "+ ntElapse.TimeStringValue );
// StringValue , DateTimeStringValue, TimeStringValue, doubleValue , intValue
msg( "" );
msg( String()+ "---- 结束: " + "运行时长: "+ ntElapse.TimeStringValue );
ntSaveToFile( fn_output_txt, Memo1->Lines->Text );
((TButton *)Sender)->Enabled = 1;
}
//---------------------------------------------------------------------------