/*-----------------------------------------
* Copyright (c) 2002,计算中心
* All rights reserved.
*
* 文件名称:Formulas.h
* 文件标识:见配置管理计划书
* 摘 要:公式集合类和公式类的声明
*
* 当前版本:0.11
* 作 者:
* 完成日期:2002年6月29日
*
* 取代版本:0.1
* 原作者 :
* 完成日期:2002年6月21日
*------------------------------------------
*/
// Formulas.h: interface for the CFormulas class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FORMULAS_H__355D4974_250C_41E9_9EE8_337D795BAC4F__INCLUDED_)
#define AFX_FORMULAS_H__355D4974_250C_41E9_9EE8_337D795BAC4F__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <afxtempl.h> //CArray模板类头文件
#include "Splimits.h" //系统限制预定义
class CFormula; //前置声明,因为CFormulas用到了CFormula类
class CFormulas : public CObject //公式集合类
{
//以下的宏定义使CFormulas类支持序列化文件
DECLARE_SERIAL( CFormulas )
public:
long SaveTextFile(CString Filename);
long GetNameNoteType(CStringArray &name, CStringArray ¬e,CStringArray &type,CString m_FormulaFileName);
//按照给定的公式文件和类型type,返回公式名到name,注释到type如果不存在这样的公式,返回空字符串
long GetNameNoteByType(CStringArray &name,CStringArray ¬e,CString m_FormulaFileName,CString type);
//按照给定的公式名称和类型,返回公式内容,如果不存在这样的公式,返回空字符串""
CString GetFormulaBodyByNameType(CString name, CString type);
//追加一个公式fa到公式集末端,不检查同名而且类型相同的公式是否已存在(不同于Add)
long AppendFormula(CFormula fa);
long FindFormula(CFormula fa); //从公式集合查找与指定公式fa的公式名和公式类型都一致的一个公式
long DelFormula(CString name, CString type); //从公式集合删除指定公式名name和公式类型type的一个公式
long LoadFile(CString Filename); //从公式文件读全部公式到公式集合
long SaveFile(CString Filename); //从公式集合读全部公式写到公式文件
long DelFormula(long recn); //从公式集合删除指定记录号的一个公式
//增加一个公式fa到公式集,如果同名而且类型相同的公式已存在,覆盖那个公式
long AddFormula(CFormula fa);
CArray <CFormula,CFormula> m_fa;//存放公式的数组
long m_reccount;//公式总数
CFormulas();//构造函数,初始化公式纪录总数,公式数组的容量
virtual ~CFormulas();
};
class CFormula : public CObject //公式类
{
//以下的宏定义使CFormula类支持序列化文件
DECLARE_SERIAL( CFormula )
private:
short si_recn;//short型公式的记录号,仅读写文件时用
long m_recn; //公式的记录号,允许范围[0,CFormulas.m_reccount-1]
CString m_name; //公式名
CString m_type; //公式类型,汉字
CString m_typechr; //公式类型,用0-9,A-Z来表示最多36种公式,字符和汉字的对照关系见Splimits.h
CString m_flag; //公式验证有效标志["0"|"1"=无效|有效]
CString m_note; //公式注释
CString m_body; //公式内容
long Trim();//清除公式名和注释字符串前后多余的空格
public:
//把公式类别由1个字符的字符串转成汉字
long FaTypeChrToChinese(const CString Chr, CString &chinese);
//把公式类别由汉字转成1个字符的字符串
long FaTypeChineseToChr(const CString chinese, CString &Chr);
//取出公式内容放到各个字段
long GetFields(long& recn,CString& name,CString& type,CString& flag,CString& note,CString& body);
CString GetRec();
//按照各个字段设置公式内容
void SetFields(long recn,CString name,CString type,CString flag,CString note,CString body);
inline long SetRecn(long recn);//设置公式的记录号
inline long GetRecn();//取公式的记录号
CFormula() { m_recn = 0; }
CFormula( const CFormula& a ) ;//这个拷贝构造函数必须保留
void Serialize( CArchive& ar);//读写公式
//重载赋值运算符=,实现CFormula对象的复制
inline const CFormula& operator=( const CFormula& a );
//重载相等运算符==,实现CFormula对象的比较
BOOL operator==(CFormula a);
#ifdef _DEBUG
void Dump( CDumpContext& dc ) const
{
CObject::Dump( dc );
dc << m_recn;
}
#endif
};
#endif // !defined(AFX_FORMULAS_H__355D4974_250C_41E9_9EE8_337D795BAC4F__INCLUDED_)
/*-----------------------------------------
* Copyright (c) 2002,计算中心
* All rights reserved.
*
* 文件名称:Formulas.cpp
* 文件标识:见配置管理计划书
* 摘 要:公式集合类和公式类的成员函数的实现
*
* 当前版本:0.1
* 作 者:
* 完成日期:2002年6月21日
*
* 取代版本:
* 原作者 :
* 完成日期:
*------------------------------------------
*/
// Formulas.cpp: implementation of the CFormulas class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//LT 20020628 FIX
#include "Sarp.h"
//LT 20020628 FIX END
#include "Formulas.h"
#define BUFSIZE 40000L
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//以下的宏定义使CFormulas类和CFormula类支持序列化文件
IMPLEMENT_SERIAL( CFormulas, CObject, VERSIONABLE_SCHEMA | 2 )
IMPLEMENT_SERIAL( CFormula, CObject, VERSIONABLE_SCHEMA | 2 )
//取公式的记录号
/*inline */long CFormula::GetRecn()
{
return m_recn;
}
//设置公式的记录号
/*inline */long CFormula::SetRecn(long recn)
{
m_recn=recn;
return m_recn;
}
//没有什么用的重载构造函数
/*
CFormula::CFormula(long recn, CString name, CString type, CString flag, CString note, CString body)
{
m_recn =recn;
m_name =name;
m_type =type;
m_flag =flag;
m_note =note;
m_body =body;
}
*/
//按照各个字段设置公式内容
void CFormula::SetFields(long recn,CString name,CString type,CString flag,CString note,CString body)
{
m_recn =recn;
m_name =name;
m_type =type;
m_flag =flag;
m_note =note;
m_body =body;
Trim();
}
CFormula::CFormula( const CFormula& a ) //这个拷贝构造函数必须保留
{
m_recn =a.m_recn;
m_name =a.m_name;
m_type =a.m_type;
m_flag =a.m_flag;
m_note =a.m_note;
m_body =a.m_body;
Trim();
} // Copy constructor
//重载赋值运算符=,实现CFormula对象的复制
/* inline */const CFormula& CFormula::operator=( const CFormula& a )
{
m_recn =a.m_recn;
m_name =a.m_name;
m_type =a.m_type;
m_flag =a.m_flag;
m_note =a.m_note;
m_body =a.m_body;
Trim();
return *this;
}
//重载相等运算符==,实现CFormula对象的比较
BOOL CFormula::operator ==(CFormula a)
{
//return m_recn == a.m_recn;//这样不保险,万一设置recn不当
//判断2个公式相等的条件应该是名字和类型都一致
// return ((m_name == a.m_name)&&( m_type == a.m_type)); //LT DEL 20020701
if(0==m_name.CompareNoCase (a.m_name ))//改为比较字符串函数,避免==的不明确 //LT 20020815 Add NOCASE
{
if(0==m_type.Compare (a.m_type ))
{
return TRUE;
}
}
return FALSE;
}
//取出公式内容放到各个字段
long CFormula::GetFields(long &recn, CString &name, CString &type, CString &flag, CString ¬e, CString &body)
{
recn =m_recn;
name =m_name;
type =m_type;
flag =m_flag;
note =m_note;
body =m_body;
return 1;
}
//取出公式内容放到字符串对象,主要供调试时观察用
CString CFormula::GetRec()
{
CString str;
str.Format ("recn:%dname:%stype:%sflag:%snote:%sbody:%s",
m_recn,m_name,m_type,m_flag,m_note,m_body.Left (20)); //防止字符串太长
return str;
}
//读写公式
void CFormula::Serialize( CArchive& ar)
{
/*原来好的开始
if( ar.IsStoring())//把CFormula对象的数据成员,而不是整个对象保存到文件
{
ar << m_recn;
ar << m_name;
ar << m_type;
ar << m_flag;
ar << m_note;
ar << m_body;
}
else //把CFormula对象的数据成员从文件读出来
{
ar >> m_recn;
ar >> m_name;
ar >> m_type;
ar >> m_flag;
ar >> m_note;
ar >> m_body;
}
原来好的结束*/
si_recn = 0;
if( ar.IsStoring())//把CFormula对象的数据成员,而不是整个对象保存到文件
{
si_recn=(short)m_recn;//把long转成short
ar << si_recn;
ar << m_name;
FaTypeChineseToChr(m_type,m_typechr);//把汉字类型转化成字符
//只用m_type一个变量不行的,在运行过程中m_type的值改变了,汉字转化成字符,成了非法的
ar << m_typechr;
ar << m_flag;
ar << m_note;
ar << m_body;
}
else //把CFormula对象的数据成员从文件读出来
{
ar >> si_recn;
m_recn=(long)si_recn;
ar >> m_name;
ar >> m_typechr;
FaTypeChrToChinese(m_typechr,m_type);//把字符转化成汉字类型
ar >> m_flag;
ar >> m_note;
ar >> m_body;
}
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFormulas::CFormulas()//构造函数,初始化公式纪录总数,公式数组的容量
{
m_reccount=0;
m_fa.SetSize(30);
}
CFormulas::~CFormulas()//应该释放一些内容
{
m_fa.RemoveAll ();
}
/*-----------------------------------------
* 函数介绍:增加一个公式到公式集合,如果同名
* 而且类型相同的公式已存在,覆盖那个公式。保证
* 增加的公式与已存在不同名、类型是程序员的责任
* 输入参数:一个CFormula的对象fa
* 输出参数:
* 返回值 :1,表示增加成功,2表示覆盖成功
*------------------------------------------
*/
long CFormulas::AddFormula(CFormula fa)
{
if(m_reccount<0) //这个条件应该永远不会达到,但为了保险还是加上
{
return 0;
}
long recn;
recn=FindFormula(fa); //效率很低
if (-1 != recn) //相同的公式已存在
{
fa.SetRecn(recn); //因为是覆盖,公式的记录号是recn
m_fa[recn]=fa;
return 2;
}
else
{
m_reccount+=1;
m_fa.Add (fa); //只有这一行不够,因为CFormula没有重载Add函数,
fa.SetRecn(m_reccount-1); //因为是追加,新纪录的记录号是m_reccount-1
m_fa[m_reccount-1]=fa; //不能自动给成员变量赋值,而=运算符是重载的
//
return 1;
}
}
/*-----------------------------------------
* 函数介绍:从公式集合删除指定记录号的一个公式
* 输入参数:一个long的对象recn
* 输出参数:
* 返回值 :1,表示增加成功,0表示删除失败
*------------------------------------------
*/
//
long CFormulas::DelFormula(long recn)
{
long i;
if((recn<0)||(recn>m_reccount)) //非法的纪录号
{
return 0;
}
if(m_reccount<1) //公式集合为空
{
return 0;
}
else //公式集合不为空(至少1个公式)
{
for(i=recn+1;i<m_reccount;i++) //重新设置recn以后的公式的记录号等于原来纪录号-1
{
m_fa[i].SetRecn (m_fa[i].GetRecn() - 1);//参数的值实际上等于i-1
}
m_fa.RemoveAt(recn);//删除记录!!使CFormulas.m_fa的下标恒等于m_fa.m_recn
m_reccount--;
return 1;
}
}
/*-----------------------------------------
* 函数介绍:从公式集合读全部公式写到公式文件
* 输入参数:一个CString的对象公式文件名
* 输出参数:
* 返回值 :1,表示写成功,0表示写失败
*------------------------------------------
*/
long CFormulas::SaveFile(CString Filename)
{
CFile myFile(Filename, CFile::modeCreate | CFile::modeReadWrite);
// CFormula foa, *pfoa;
// Create a storing archive.
CArchive arStore(&myFile, CArchive::store);
CString m_fileflag="Sarp2002";
arStore << m_fileflag;
//arStore << m_reccount; //LT DEL 20020629
//LT ADD 20020629
short si_reccount=(short)m_reccount;
arStore << si_reccount;
//LT ADD 20020629 END
long i=0;
for(i=0;i<m_reccount;i++)
{
//arStore << &m_fa[i];//LT DEL 20020629
//直接调用CArchive对象的Serialize函数
arStore.WriteObject( &m_fa[i] );//LT ADD 20020629
}
arStore.Close();
myFile.Close ();
return 1;
}
/*-----------------------------------------
* 函数介绍:从公式文件读全部公式到公式集合
* 输入参数:一个CString的对象公式文件名
* 输出参数:
* 返回值 :1,表示读成功,0表示读失败
*------------------------------------------
*/
long CFormulas::LoadFile(CString Filename)
{
CFileFind finder;
// start working for files
BOOL b_find = finder.FindFile(Filename);
if(0==b_find)
{
return 0;
}
CFile myFile(Filename, CFile::modeRead);
CFormula foa, *pfoa;
CArchive arLoad(&myFile, CArchive::load);
CString m_fileflag="Sarp2002";
short si_reccount=0;
arLoad >> m_fileflag;
//arLoad >> m_reccount; //LT DEL 20020629
//LT FIX 20020629
arLoad >> si_reccount;
m_reccount=(long)si_reccount;
//LT FIX 20020629 END
if(m_reccount<=0)//1个公式都没有
{
return 0;
}
long i=0;
m_fa.SetSize(m_reccount); //LT MODI 20020810
for(i=0;i<m_reccount;i++)
{
//arLoad >> pfoa; //LT FIX 20020629
//函数使用范例pAge = (CAge*) arLoad.ReadObject( RUNTIME_CLASS(CAge) );
/* good
pfoa=(CFormula*)arLoad.ReadObject( RUNTIME_CLASS(CFormula));//直接调用CArchive对象的Serialize函数
m_fa.Add (foa);
m_fa[i]=*pfoa;
*/
//LT MODI 20020810
arLoad >> pfoa;
m_fa[i]=*pfoa;
delete pfoa; //消除内存泄漏
}
arLoad.Close();
myFile.Close ();
return 1;
}
/*-----------------------------------------
* 函数介绍:从公式集合删除指定公式名和公式类型的一个公式
* 输入参数:一个CString的对象公式名,一个CString的对象公式类型
* 输出参数:
* 返回值 :1,表示删除成功,0表示删除失败
*------------------------------------------
*/
long CFormulas::DelFormula(CString name, CString type)
{
//查找符合条件的纪录
//返回记录号
//调用另一个DelFormula(long recn)函数
long recn;
CFormula fa;
fa.SetFields (-1,name,type,"","","");
recn=FindFormula(fa);
return DelFormula(recn);
}
/*-----------------------------------------
* 函数介绍:从公式集合查找指定公式名和公式类型的一个公式
* 输入参数:一个CFormula的对象fa
* 输出参数:
* 返回值 :>=0表示查找成功,-1表示查找失败
*------------------------------------------
*/
long CFormulas::FindFormula(CFormula fa)
{
long i;
for(i=0;i<m_reccount;i++)
{
// TRACE("i=%d,s=%s,a=%s",i,m_fa[i].GetRec() ,fa.GetRec() );
if(m_fa[i]==fa)
{
return i;
}
}
return -1;
}
/*-----------------------------------------
* 函数介绍:追加一个公式到公式集合末端,不检查同名
* 而且类型相同的公式是否已存在(不同于Add)。保证
* 增加的公式与已存在不同名、类型是程序员的责任
* 输入参数:一个CFormula的对象fa
* 输出参数:
* 返回值 :1,表示追加成功,2表示覆盖成功
*------------------------------------------
*/
long CFormulas::AppendFormula(CFormula fa)
{
if(m_reccount<0) //这个条件应该永远不会达到,但为了保险还是加上
{
return 0;
}
else
{
m_reccount+=1;
m_fa.Add (fa); //只有这一行不够,因为CFormula没有重载Add函数,
fa.SetRecn(m_reccount-1); //因为是追加,新纪录的记录号是m_reccount-1
m_fa[m_reccount-1]=fa; //不能自动给成员变量赋值,而=运算符是重载的
//
return 1;
}
}
//清除公式名和注释字符串前后多余的空格
long CFormula::Trim()
{
m_name.TrimLeft ();
m_name.TrimRight ();
m_note.TrimLeft ();
m_note.TrimRight ();
return 1;
}
//按照给定的公式名称和类型,返回公式内容,如果不存在这样的公式,返回空字符串""
//#include "mainfrm.h"
CString CFormulas::GetFormulaBodyByNameType(CString name, CString type)
{
// CMainFrame *MFrame=(CMainFrame *)AfxGetMainWnd();//获得指向框架的指针
CFormulas cf;
//MFrame->
GetFormulaFileName();
LoadFile (FormulaFileName);
CFormula fa;
CString str_name,str_type,str_flag,str_note,str_body;
long l_recn;
fa.SetFields(-1, name, type,"","","");
CString str_chtype="";
fa.FaTypeChineseToChr(type,str_chtype);
l_recn = FindFormula(fa);
if(-1!=l_recn)
{
m_fa[l_recn].GetFields(l_recn,str_name,str_type,str_flag,str_note,str_body);
//除了指针以外的公式最后补/n
if((str_chtype>='0'&&str_chtype<='9')//指针都>9
&&str_body.GetAt(str_body.GetLength()-1)!='/n') //20020814, add '/n' at end of string
{
str_body=str_body+"/n";
}
return str_body;
}
else
{
if(str_chtype>='0'&&str_chtype<='9')
{
return "/n"; //20020814
}
return "";
}
}
//把公式类别由汉字转成1个字符的字符串
//参数:CString chinese公式类别汉字
//CString &Chr,转换后的字符串,只有一个字符
//如果没有匹配,Chr==空字符串""
//返回值,转化成功后的字符的ASC值,失败返回-1
long CFormula::FaTypeChineseToChr(const CString chinese, CString &Chr)
{
CString str_fulltype=STRING_FORMULA_TYPES_CHAR;
if(chinese.GetLength ()<2)//汉字必然>=2个字符
{
#ifdef _DEBUG
// AfxMessageBox("非法的汉字公式类型["+chinese+"]");
#endif
Chr="";
return -1;
}
long i=str_fulltype.Find(chinese);
if(-1==i)
{
#ifdef _DEBUG
// AfxMessageBox("找不到的汉字公式类型["+chinese+"]");
#endif
Chr="";
return -1;
}
else
{
//LT030405 Chr=str_fulltype[i-1];//如果找到,i必然>=1
Chr=str_fulltype.Mid(i-1,1);//如果找到,i必然>=1
//LT030405 return (long)str_fulltype[i-1];
return (long)(str_fulltype.GetAt (i-1));
}
}
//把公式类别由1个字符的字符串转成汉字
//参数:CString Chr,转换前的字符串,只有一个字符
//CString &chinese 转换后的公式类别汉字
//如果没有匹配,chinese==空字符串""
//返回值,转化成功后返回1,失败返回-1
long CFormula::FaTypeChrToChinese(const CString Chr, CString &chinese)
{
CString str_fulltype=STRING_FORMULA_TYPES_CHAR;
if(1!=Chr.GetLength ())//必然==1个字符
{
#ifdef _DEBUG
// AfxMessageBox("非法的字符公式类型");
#endif
chinese="";
return -1;
}
long i=str_fulltype.Find(Chr);
if(-1==i)
{
#ifdef _DEBUG
// AfxMessageBox("找不到的字符公式类型");
#endif
chinese="";
return -1L;
}
else
{
long j=str_fulltype.Find ("|",i);//如果找到,j必然>i+1
chinese=str_fulltype.Mid (i+1,j-i-1);
return 1L;
}
}
//按照给定的公式文件和类型type,返回公式名到name,注释到type如果不存在这样的公式,返回空字符串
long CFormulas::GetNameNoteByType(CStringArray &name, CStringArray ¬e,CString m_FormulaFileName,CString type)
{
long loadok=LoadFile (m_FormulaFileName);
// long FindSeltypefa=0;
name.RemoveAll ();
note.RemoveAll ();
long l_recn=0;
CString str_name;//公式名
CString str_type;//公式类型
CString str_flag;//公式有效标志[0|1=无效|有效]
CString str_note;//公式注释
CString str_body;//公式内容
if(loadok>0) //文件中有至少1个公式
{
long i;
for(i=0;i<m_reccount;i++)
{
m_fa[i].GetFields ( l_recn,
str_name,str_type,str_flag,str_note,str_body );
//应该只显示选择类型的公式
if(str_type==type)
{
name.Add (str_name);
note.Add (str_note);
}
}
return 1;
}
return 0;
}
long CFormulas::GetNameNoteType(CStringArray &name, CStringArray ¬e,CStringArray &type,CString m_FormulaFileName)
{
long loadok=LoadFile (m_FormulaFileName);
// long FindSeltypefa=0;
name.RemoveAll ();
note.RemoveAll ();
type.RemoveAll ();
long l_recn=0;
CString str_name;//公式名
CString str_type;//公式类型
CString str_flag;//公式有效标志[0|1=无效|有效]
CString str_note;//公式注释
CString str_body;//公式内容
if(loadok>0) //文件中有至少1个公式
{
long i;
for(i=0;i<m_reccount;i++)
{
m_fa[i].GetFields ( l_recn,
str_name,str_type,str_flag,str_note,str_body );
//应该只显示选择类型的公式
// if(str_type==type)
{
name.Add (str_name);
note.Add (str_note);
type.Add (str_type);
}
}
return 1;
}
return 0;
}
long CFormulas::SaveTextFile(CString Filename)
{
CFile myFile(Filename, CFile::modeCreate | CFile::modeReadWrite);
short si_reccount=(short)m_reccount;
long i=0;
long j=0;
char buf[BUFSIZE];
CString str,strname,strtype,strflag,strnote,strbody;
for(i=0;i<m_reccount;i++)
{
str.Format ("%u/r/n",i);
m_fa[i].GetFields(j,strname,strtype,strflag,strnote,strbody);
str=str+"公式名:"+strname+"/r/n"
"公式类型:"+strtype+"/r/n"
"公式注释:"+strnote+"/r/n"
"公式内容:/r/n"+strbody+"/r/n/007";
strcpy(buf,(LPCSTR)str);
myFile.Write (buf,strlen(buf));
}
myFile.Close ();
return 1;
}