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