Easy reporting in C / C ++
If you are developing in C / C ++ any software for operators (administrators) of hospitals, shops, gyro scooter rental services, cell phone repair services, then you probably faced the task of creating reports in order to print them on a printer, or at least in PDF. There are many third-party packages for Embarcadero RAD Studio that allow you to do this. Such as FastReport, QuickReport, Crystal Reports, etc. But in my opinion, all these packages require a deep understanding of their mechanism and interface. It takes a lot of time to study them, and most importantly, the code for generating even the simplest report will consist of a huge number of lines. When I first encountered the task of generating reports under C / C ++, I started with FastReport and realized that I absolutely did not like this tool.
At that very moment, a wonderful thought came to my mind: how cool it would be to take a simple EXCEL file, add static information to it and format it to fit your needs. The program will only open this file, fill it with dynamic data and save or send to print! This served as a starting point for my study of the OLE mechanism for working with MS Office files from programs developed in Embarcadero RAD Studio.
In the course of my work, I managed to delve deeply enough into the topic and now I can say with confidence that all the tools that MS Office and OLE provide provide that cover all my reporting needs. Well, if so, then probably for other developers it would be a self-sufficient, simple and convenient tool. Therefore, it was decided to write a DLL and pack into it a list of all commonly used MS Excel functions that you encounter during the creation of Excel documents. This is very convenient, because in order to create a report, you do not need to study a bunch of manuals or OLE. All that is required is just to load the DLL and its functions. Well, many are able to work with DLLs.
Here is the site of the project itself .
On the project site, the mechanism for working with DLLs is described in sufficient detail; there is an example and description of all the functions.
The DLL comes without a header file and without a static LIB library. Thus, the DLL must be connected dynamically using the LoadLibrary function. The ZIP archive with the library includes the following files:
The header file for the LPDLL.h library usage example contains the following declarations:
The LPDLL.h file already contains everything you need to work with the DLL and its functions. But you can also edit it or take only the most necessary for your project.
Imagine that you just connected the header file “LPDLL.h” to your project .
Then, in the project itself, you simply need to:
1) Declare a variable handle to your report:
2) Dynamically load the DLL and all its functions:
3) Next, in the try-catch construct, open the prepared report template (MS Excel file):
4) Add some data to the report:
...
5) Save the file or print:
6) Close the file:
7) Unload the DLL library:
And that’s it! Absolutely nothing more! There is only one caveat, but even that, it appears only during debugging. In a working application, everything will work well. I mean a situation in which there is some kind of error when working with a report. The fact is that the OLE mechanism for working with documents involves only throwing exceptions when errors occur. That's why when working with DLL functions, you must use the try-catch construct. In the catch block, you must close the report without saving:
When debugging, when an error occurs, you can stop the program. In this case, the MS Excel process will remain running, and it will be possible to close it only through the task manager. Therefore, when you repeatedly debug the application, several instances of the MS Excel process can be launched, depending on how often you pause the program when an error occurs, without waiting for the code to execute in catch. This must be monitored.
In the release, if an error occurs, the code specified in the catch block will definitely work, the report will close, and the MS Excel process will be completed. No MS Excel processes hanging in the system will be observed. But still they try to write error-free code, so I hope you do not have this situation in a running application.
Finally, you need to add:
Therefore, for the future it is planned to pack all the functionality into a class and hide this Variant format inside the class so that only the generally accepted C / C ++ formats are provided to the user. I have never tried packing classes into DLLs, I read that difficulties will necessarily arise with this. Nevertheless, we will understand! In the meantime, thank you for your attention, I will be very happy if this article and the DLL help someone.
Link to the project .
At that very moment, a wonderful thought came to my mind: how cool it would be to take a simple EXCEL file, add static information to it and format it to fit your needs. The program will only open this file, fill it with dynamic data and save or send to print! This served as a starting point for my study of the OLE mechanism for working with MS Office files from programs developed in Embarcadero RAD Studio.
In the course of my work, I managed to delve deeply enough into the topic and now I can say with confidence that all the tools that MS Office and OLE provide provide that cover all my reporting needs. Well, if so, then probably for other developers it would be a self-sufficient, simple and convenient tool. Therefore, it was decided to write a DLL and pack into it a list of all commonly used MS Excel functions that you encounter during the creation of Excel documents. This is very convenient, because in order to create a report, you do not need to study a bunch of manuals or OLE. All that is required is just to load the DLL and its functions. Well, many are able to work with DLLs.
Here is the site of the project itself .
On the project site, the mechanism for working with DLLs is described in sufficient detail; there is an example and description of all the functions.
The DLL comes without a header file and without a static LIB library. Thus, the DLL must be connected dynamically using the LoadLibrary function. The ZIP archive with the library includes the following files:
- " light_report.dll " - the DLL library itself;
- " DLLTest.cpp " - an example of using the library;
- " LPDLL.h " - the header file for an example of using the library (this is not the header file of the DLL);
- " Report.xlsx " - MS EXCEL document for an example of using the library.
The header file for the LPDLL.h library usage example contains the following declarations:
- enumerations that are used as arguments to DLL functions;
- types of DLL functions;
- DLL function instances
- DLL download descriptor (" HINSTANCE DLL_Handle; ");
- function LoadLightReportDLL , which dynamically loads the DLL and all its functions;
- FreeLightReportDLL function that unloads the DLL.
The LPDLL.h file already contains everything you need to work with the DLL and its functions. But you can also edit it or take only the most necessary for your project.
Imagine that you just connected the header file “LPDLL.h” to your project .
Then, in the project itself, you simply need to:
1) Declare a variable handle to your report:
Variant report;
2) Dynamically load the DLL and all its functions:
if(!LoadLightReportDLL("C:\\LightReport\\light_report.dll"))return;
3) Next, in the try-catch construct, open the prepared report template (MS Excel file):
report=OpenReport("C:\\LightReport\\Report.xlsx",0);
4) Add some data to the report:
WriteCell(report, "Sheet1", 9, 1, "Hello world!");
...
5) Save the file or print:
Save(report);
SaveAs(report, "C:\\LightReport\\Report copy.xlsx");
ExportToPDF(report, "C:\\LightReport\\Report.pdf", false);
PrintOut(report);
6) Close the file:
CloseReport(report);
7) Unload the DLL library:
FreeLightReportDLL();
And that’s it! Absolutely nothing more! There is only one caveat, but even that, it appears only during debugging. In a working application, everything will work well. I mean a situation in which there is some kind of error when working with a report. The fact is that the OLE mechanism for working with documents involves only throwing exceptions when errors occur. That's why when working with DLL functions, you must use the try-catch construct. In the catch block, you must close the report without saving:
catch(...){CloseReport(report);}
. When debugging, when an error occurs, you can stop the program. In this case, the MS Excel process will remain running, and it will be possible to close it only through the task manager. Therefore, when you repeatedly debug the application, several instances of the MS Excel process can be launched, depending on how often you pause the program when an error occurs, without waiting for the code to execute in catch. This must be monitored.
In the release, if an error occurs, the code specified in the catch block will definitely work, the report will close, and the MS Excel process will be completed. No MS Excel processes hanging in the system will be observed. But still they try to write error-free code, so I hope you do not have this situation in a running application.
Finally, you need to add:
- The DLL uses platform-independent data types, such as unsigned short , unsigned long, and char . This is understandable why.
- The example is written in the Embarcadero Builder C ++ 10 environment. Accordingly, all the code corresponds to this environment and, perhaps, you will need to make some changes to the example code to make everything work in your environment.
- The bottleneck of this DLL is the use of the report file descriptor in Variant format . This is a rather specific format and I suspect that it may be difficult to use the library outside Embarcadero RAD Studio. Honestly, I did not check.
Therefore, for the future it is planned to pack all the functionality into a class and hide this Variant format inside the class so that only the generally accepted C / C ++ formats are provided to the user. I have never tried packing classes into DLLs, I read that difficulties will necessarily arise with this. Nevertheless, we will understand! In the meantime, thank you for your attention, I will be very happy if this article and the DLL help someone.
Link to the project .