BCB 之 C++Builder XE 之 Excel 数据整合

下载: 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;
}
//---------------------------------------------------------------------------

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值