11 KiB
数据导出
**本文档引用的文件** - [TdManager.cpp](file://cpp/Managers/TdManager.cpp) - [IOManager.cpp](file://cpp/Managers/IOManager.cpp) - [excel.cpp](file://cpp/Tools/excel.cpp) - [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp) - [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp) - [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp) - [Rsp2DTd.cpp](file://cpp/ProblemZone/Rsp2DTd.cpp) - [RspCETd.cpp](file://cpp/ProblemZone/RspCETd.cpp) - [SP2DTd.cpp](file://cpp/ProblemZone/SP2DTd.cpp) - [TdManager.h](file://h/TdManager.h) - [IOManager.h](file://h/IOManager.h) - [excel.h](file://h/excel.h) - [OperTxtFile.h](file://h/OperTxtFile.h) - [OperUrfFile.h](file://h/OperUrfFile.h) - [ioexpdlg.cpp](file://cpp/Views/ioexpdlg.cpp) - [ioexpdmsdlg.cpp](file://cpp/Views/ioexpdmsdlg.cpp) - [ioexpsptdlg.cpp](file://cpp/Views/ioexpsptdlg.cpp) - [ioexpdlg.h](file://h/ioexpdlg.h) - [ioexpdmsdlg.h](file://h/ioexpdmsdlg.h) - [ioexpsptdlg.h](file://h/ioexpsptdlg.h)目录
引言
本文档旨在全面文档化Geomative Studio软件中测试数据导出功能的实现。该功能主要由CTdManager和CIOManager两个核心管理类协同工作,支持将测试数据导出为Excel、CSV、TXT、URF等多种格式。文档将详细阐述其技术细节,包括不同格式的数据结构映射规则、用户自定义选项的处理逻辑、Excel导出中excel.cpp类库的使用流程,以及导出过程中的进度反馈、错误处理和内存优化策略。
核心组件分析
CTdManager和CIOManager是实现数据导出功能的两个核心类。
CTdManager类(位于cpp/Managers/TdManager.cpp)是测试数据的管理核心。它负责从数据库中获取测试数据,并提供将数据保存为特定文件格式的接口。例如,CRsp2DTd和CRspCETd等具体的数据类型类继承自CTestingData,并实现了SaveTdToExcelFile和SaveTdToCsvFile等方法,这些方法定义了如何将特定类型的数据组织并写入文件。
CIOManager类(位于cpp/Managers/IOManager.cpp)则负责更高层次的导出流程控制。其Export方法启动导出流程,创建一个导出对话框(CIOExpDlg),用户可以在其中选择要导出的项目、测区和具体的测试数据。CIOManager根据用户的选择,调用CTdManager提供的接口来执行实际的数据导出操作。
Section sources
数据导出格式与数据结构映射
系统支持将测试数据导出为四种主要格式:Excel、CSV、TXT和URF。每种格式都有其特定的数据结构映射规则。
对于Excel和CSV格式,数据通常被组织成多个工作表或数据块。以CRsp2DTd类为例,其SaveTdToExcelFile方法会创建一个Excel工作簿,并包含三个工作表:
- Head (头部信息): 包含测试任务的元数据,如任务名称、位置、日期、设备信息等。
- DAT (数据信息): 包含核心的测量数据,如电极配置(A, B, M, N)、视电阻率(Ro)、电压(V)、电流(I)等。
- GR (接地电阻): 包含各电极的接地电阻测量值。
TXT格式的导出由COperTxtFile类(位于cpp/Tools/OperTxtFile.cpp)处理。该类提供了一个可配置的文本文件写入器,通过SetParamWidth方法设置每列的宽度,并使用WriteFileContent方法将字符串数组按固定宽度写入文件,确保数据在文本编辑器中对齐。
URF(Universal Resistivity data File)是一种专用于电阻率数据的通用格式。其导出由COperUrfFile类(位于cpp/Tools/OperUrfFile.cpp)负责。URF文件的结构包括一个头部注释,然后是电极坐标信息,最后是测量数据。COperUrfFile类提供了针对不同电极阵列(如温纳装置、施伦贝谢装置、跨孔装置等)生成电极坐标的专用方法,如WriteElecByWenSch和WriteElecByCrossHoleGeomative,确保导出的URF文件符合特定的地质勘探软件要求。
Section sources
Excel导出功能实现
Excel导出功能的核心是excel.cpp和excel.h文件。这两个文件是通过Visual C++的ClassWizard工具从Microsoft Excel的类型库生成的C++包装类,它们提供了对Excel应用程序对象模型的COM接口访问。
导出过程遵循以下操作流程:
-
创建Excel应用实例:
_Application* pComApp = new _Application;这行代码创建了一个Excel应用程序的COM对象实例。
-
创建和获取工作簿与工作表:
Workbooks comBooks; _Workbook comBook; Sheets comSheets; _Worksheet comSheet01;通过
_Application对象,可以获取Workbooks集合,进而创建一个新的工作簿(comBook),并从工作簿中获取Sheets集合来操作具体的工作表。 -
创建工作表并命名:
comSheet01 = comSheets.GetItem(COleVariant((short)1)); comSheet01.SetName(_T("Head"));使用
GetItem方法获取第一个工作表,并使用SetName方法将其重命名为"Head"。 -
写入数据: 具体的数据写入逻辑由
CTestingData的派生类(如CRsp2DTd)实现。这些类会调用SaveTdHeadToExcelFile等方法,通过遍历数据库记录集(_RecordsetPtr),并将数据逐行写入到_Worksheet对象的单元格中。 -
应用样式和公式: 虽然在提供的代码片段中未直接体现,但
_Worksheet和Range对象提供了丰富的属性和方法来设置单元格格式(如字体、颜色、边框)和应用公式。例如,可以通过GetRange方法获取一个单元格区域,然后设置其NumberFormat属性来定义数字显示格式。 -
保存并清理:
comBook.SaveAs(COleVariant(f_szFileName), covOptional, ...); ... pComApp->Quit(); delete pComApp;使用
SaveAs方法将工作簿保存到指定路径。最后,必须显式调用Quit方法退出Excel应用,并释放所有COM对象指针,以避免内存泄漏。
Section sources
用户自定义导出选项处理
用户自定义导出选项主要通过导出对话框(CIOExpDlg)来处理。该对话框由CIOManager在Export方法中创建。
-
字段选择: 对话框中的树形控件(
CTreeCtrl)允许用户通过复选框选择要导出的具体项目、测区和测试数据。CIOManager通过遍历树形控件,检查每个节点的选中状态,来确定最终需要导出的数据集。 -
时间范围和单位系统: 在提供的代码中,时间范围和单位系统的处理逻辑并未直接体现。这些选项很可能在
CTestingData类的SaveTdTo...File方法内部实现。当从数据库查询数据时,会根据用户在UI中选择的时间范围构建SQL查询语句的WHERE子句。单位系统(如米/英尺)的转换则可能在数据写入文件之前,在内存中对数值进行换算。
Section sources
导出过程中的进度反馈与错误处理
进度反馈
在提供的代码中,导出过程是同步执行的,没有明确的进度条或百分比反馈机制。整个过程在用户点击“确定”后,直到完成或出错才会返回控制权。更完善的实现可能需要在CIOManager或CTdManager中引入后台线程,并通过Windows消息或回调函数向UI发送进度更新。
错误处理
系统采用了多层次的错误处理策略:
- 文件操作错误: 在打开或写入文件时,会检查返回值(如
fopen是否返回NULL)。如果失败,会通过AfxMessageBox或MessageBoxEx向用户显示错误信息,包括错误代码(GetLastError())。 - 数据库操作错误: 使用
try-catch块捕获_com_error异常,当执行数据库查询或操作失败时,会弹出错误对话框。 - 逻辑错误: 在执行关键操作前进行参数验证。例如,
COperTxtFile::SetParamWidth会检查输入的宽度是否在有效范围内(6-50),否则会提示错误。 - COM接口错误: 在使用
excel.cpp进行Excel操作时,虽然代码中没有显式捕获异常,但应假设_Application等对象的方法调用可能失败,需要进行返回值检查。
Section sources
大文件生成的内存优化方案
对于大文件的生成,系统主要通过以下方式优化内存使用:
- 流式写入 (Streaming): 所有文件导出操作都采用流式写入。无论是TXT、CSV还是URF文件,代码都是在打开文件后,一边从数据库读取记录,一边立即写入文件流(
fwrite),然后立即处理下一条记录。这种方式避免了将整个数据集加载到内存中,从而将内存占用保持在较低水平。 - 分块处理: 数据库查询使用
_RecordsetPtr,它本质上是一个游标,允许逐行遍历结果集,而不是一次性将所有数据加载到内存。 - 及时释放资源: 在操作完成后,代码会显式关闭文件句柄(
fclose)、关闭数据库记录集(Close())并释放COM对象(ReleaseDispatch()),确保资源被及时回收。
Section sources