We value your input! Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey
2023-12-01 01:38 PM - last edited on 2024-09-16 02:43 PM by Doreena Deng
Hello,
I've developed a plugin for Archicad that extracts building elements from a drawing. Currently, my plugin displays the results in a pop-up window using the ACAPI_WriteReport() function. However, I now need to enhance its functionality to export these elements into a CSV or TXT file. I couldn't find any specific API functions in the Archicad API documentation to handle this type of export.
Does anyone have experience or suggestions on how to implement this feature? Are there alternative methods or practices within the API that I might have overlooked for exporting data into CSV or TXT formats?
Any guidance or examples would be greatly appreciated.
Thank you for your support.
Solved! Go to Solution.
2023-12-21 12:35 AM
I've developed a solution to extract building elements (walls, slabs, doors, etc.) and their properties (including embedded doors, info strings, and bounding boxes) to a text file using the Archicad API in C++.
Here's an overview of the process:
// Function to report properties of an element
void ReportElementProperties(const API_Guid& elementGuid, API_ElemTypeID elemType, std::ofstream& outFile) {
char reportStr[1024];
API_Element element;
BNZeroMemory(&element, sizeof(API_Element));
element.header.guid = elementGuid;
if (ACAPI_Element_Get(&element) == NoError) {
// Construct a report string based on the element type and its properties
// The details of this implementation will depend on what information you want to extract
// For example: sprintf(reportStr, "Element Type: %s, GUID: %s", ...);
outFile << reportStr << std::endl;
}
}
Initialization:
// Initialize function
GSErrCode __ACENV_CALL Initialize(void) {
GSErrCode err = ACAPI_MenuItem_InstallMenuHandler(AddOnMenuID, MenuCommandHandler);
// Open the output file for writing
outFile.open("ElementInfo.txt");
return err;
}
// Output file for element information
std::ofstream outFile;
Regards...
2023-12-03 04:15 PM - edited 2023-12-03 04:16 PM
this is my csv writer:
i did not test it if it works with the ac27 API since im in the middle of porting my add-on from ac26 to ac27 API.
void CsvWriter::WriteCSV(IO::Location location, GS::Array<std::wstring> towrite)
{
GSErrCode err;
//UInt32 bufSize;
IO::File csvFile(location, IO::File::Create);
err = csvFile.GetStatus();
if (err != NoError)
{
ACAPI_WriteReport("ERROR IN FILE CREATE!", true);
}
// Write the buffer into the file
err = csvFile.Open(IO::File::WriteEmptyMode);
if (err == NoError)
{
const char textHead[] = "EBKPHKlasse;Teilobjekt;Menge;EbkpCode\n";
GS::USize lenHead = sizeof(textHead);
csvFile.WriteBin(textHead, lenHead);
for (std::wstring & wstr : towrite)
{
//ACAPI_WriteReport(Auxillary::ToUniString(wstr), false);
char* outputString = (char*)malloc(100 * sizeof(char));
outputString = convertWStringToCharPtr2(wstr, outputString);
GS::USize len = 0;
while (outputString[len] != '\0')
{
len++;
}
csvFile.WriteBin(outputString, len);
}
csvFile.Close();
}
ACAPI_WriteReport(Auxillary::ToUniString(err), false);
}
you might wanna optimize the case windows vs mac.
" I couldn't find any specific API functions in the Archicad API documentation to handle this type of export."
there are a good examples in the example folder how wo export xml's etc. 🙂
2023-12-05 01:01 AM
#include "APIEnvir.h"
#include "ACAPinc.h" // Also includes APIdefs.h
#include "APICommon.h"
#include "ResourceIds.hpp"
#include "IO.hpp" // Include the necessary file IO headers
// Forward declaration of functions
static GSErrCode __ACENV_CALL MenuCommandHandler(const API_MenuParams* menuParams);
void ProcessBuildingElements();
void ReportElementProperties(const API_Guid& elementGuid, API_ElemTypeID elementType);
// Unique IDs for the Add-On (change these to actual unique IDs)
static const GSResID AddOnInfoID = ID_MY_ADDON_INFO;
static const Int32 AddOnNameID = 1;
static const Int32 AddOnDescriptionID = 2;
static const short AddOnMenuID = ID_MY_ADDON;
static const Int32 AddOnCommandID = 1;
// Check environment function
API_AddonType __ACDLL_CALL CheckEnvironment(API_EnvirParams* envir)
{
// Set the Add-On's name and description
RSGetIndString(&envir->addOnInfo.name, 32000, 1, ACAPI_GetOwnResModule());
RSGetIndString(&envir->addOnInfo.description, 32000, 2, ACAPI_GetOwnResModule());
return APIAddon_Preload;
} // CheckEnvironment
// Register interface function
GSErrCode __ACENV_CALL RegisterInterface(void)
{
GSErrCode err = ACAPI_MenuItem_RegisterMenu(AddOnMenuID, 0, MenuCode_UserDef, MenuFlag_Default);
return err;
}
// Initialize function
GSErrCode __ACENV_CALL Initialize(void)
{
GSErrCode err = ACAPI_MenuItem_InstallMenuHandler(AddOnMenuID, MenuCommandHandler);
return err;
}
// Free data function
GSErrCode __ACENV_CALL FreeData(void)
{
return NoError;
}
// Function to process building elements
void ProcessBuildingElements()
{
GS::Array<std::wstring> elementInfo; // Store the information you want to export to CSV
API_ElemTypeID elementTypes[] = { API_WallID, API_SlabID };
for (API_ElemTypeID elementType : elementTypes) {
GS::Array<API_Guid> elementList;
if (ACAPI_Element_GetElemList(elementType, &elementList) == NoError && !elementList.IsEmpty()) {
for (const API_Guid& elementGuid : elementList) {
// Retrieve element properties and format them as a string
std::wstring elementInfoStr = GetElementInfoString(elementGuid, elementType);
// Add the formatted string to the elementInfo array
elementInfo.Push(elementInfoStr);
}
}
}
// Specify the location where you want to save the CSV file
IO::Location csvLocation("C:\\API Development Kit 27.3001\\Server Add on\\YourFile.csv");
// Call the CsvWriter::WriteCSV function to export the information to the CSV file
CsvWriter::WriteCSV(csvLocation, elementInfo);
}
// Function to report properties of an element
void ReportElementProperties(const API_Guid& elementGuid, API_ElemTypeID elementType)
{
char reportStr[1024];
// Retrieve the localized name of the element type
GS::UniString elemName;
if (ACAPI_Element_GetElemTypeName(elementType, elemName) == NoError) {
sprintf(reportStr, "Element Type: %s, GUID: %s", (const char*)elemName.ToCStr(), APIGuidToString(elementGuid).ToCStr().Get());
}
else {
sprintf(reportStr, "Element Type: %d, GUID: %s", elementType, APIGuidToString(elementGuid).ToCStr().Get());
}
// Additional property retrieval can be added here using Archicad's API functions
ACAPI_WriteReport(reportStr, true);
}
class CsvWriter
{
public:
static void WriteCSV(IO::Location location, GS::Array<std::wstring> towrite)
{
GSErrCode err;
IO::File csvFile(location, IO::File::Create);
err = csvFile.GetStatus();
if (err != NoError)
{
ACAPI_WriteReport("ERROR IN FILE CREATE!", true);
}
err = csvFile.Open(IO::File::WriteEmptyMode);
if (err == NoError)
{
const char textHead[] = "EBKPHKlasse;Teilobjekt;Menge;EbkpCode\n";
GS::USize lenHead = sizeof(textHead);
csvFile.WriteBin(textHead, lenHead);
for (std::wstring& wstr : towrite)
{
char* outputString = (char*)malloc(100 * sizeof(char));
// Implement the function convertWStringToCharPtr2 to convert wstring to char*
outputString = convertWStringToCharPtr2(wstr, outputString);
GS::USize len = 0;
while (outputString[len] != '\0')
{
len++;
}
csvFile.WriteBin(outputString, len);
}
csvFile.Close();
}
ACAPI_WriteReport(Auxillary::ToUniString(err), false);
}
// ... Other CsvWriter class members ...
};
// Menu command handler function
static GSErrCode __ACENV_CALL MenuCommandHandler(const API_MenuParams* menuParams)
{
if (menuParams->menuItemRef.menuResID == ID_MY_ADDON) {
if (menuParams->menuItemRef.itemIndex == 1) {
ProcessBuildingElements();
}
}
return NoError;
}
// Main function or other necessary functions
// ...
@Joel Buehler Thank you very much for the suggestion. I tried to implement the code but received so many errors.I could not address some of these errors.I would appreciate if you could let me now how to fix some of these errors.
Severity Code Description Project File Line Suppression State
Error (active) E1696 cannot open source file "IO.hpp" Extraction_V2.apx - x64-Debug C:\API Development Kit 27.3001\Server Add on\Extraction_V2\Src\Extraction_V2.cpp 5
Error (active) E0065 expected a ';' Extraction_V2.apx - x64-Debug C:\API Development Kit 27.3001\Server Add on\Extraction_V2\Src\Extraction_V2.cpp 106
Error (active) E0020 identifier "convertWStringToCharPtr2" is undefined Extraction_V2.apx - x64-Debug C:\API Development Kit 27.3001\Server Add on\Extraction_V2\Src\Extraction_V2.cpp 124
Error (active) E0020 identifier "csvFile" is undefined Extraction_V2.apx - x64-Debug C:\API Development Kit 27.3001\Server Add on\Extraction_V2\Src\Extraction_V2.cpp 107
Error (active) E0020 identifier "GetElementInfoString" is undefined Extraction_V2.apx - x64-Debug C:\API Development Kit 27.3001\Server Add on\Extraction_V2\Src\Extraction_V2.cpp 67
Error (active) E0276 name followed by '::' must be a class or namespace name Extraction_V2.apx - x64-Debug C:\API Development Kit 27.3001\Server Add on\Extraction_V2\Src\Extraction_V2.cpp 113
Error (active) E0276 name followed by '::' must be a class or namespace name Extraction_V2.apx - x64-Debug C:\API Development Kit 27.3001\Server Add on\Extraction_V2\Src\Extraction_V2.cpp 138
Error (active) E0135 namespace "IO" has no member "File" Extraction_V2.apx - x64-Debug C:\API Development Kit 27.3001\Server Add on\Extraction_V2\Src\Extraction_V2.cpp 106
2023-12-05 11:49 PM
You might look into something called LibXL.
We have used it with great success.
https://www.libxl.com/home.html
Best of luck,
Chris
Disclaimer:
And I am in no way associated with the creation or distribution of this utility, only a happy user.
2023-12-21 12:35 AM
I've developed a solution to extract building elements (walls, slabs, doors, etc.) and their properties (including embedded doors, info strings, and bounding boxes) to a text file using the Archicad API in C++.
Here's an overview of the process:
// Function to report properties of an element
void ReportElementProperties(const API_Guid& elementGuid, API_ElemTypeID elemType, std::ofstream& outFile) {
char reportStr[1024];
API_Element element;
BNZeroMemory(&element, sizeof(API_Element));
element.header.guid = elementGuid;
if (ACAPI_Element_Get(&element) == NoError) {
// Construct a report string based on the element type and its properties
// The details of this implementation will depend on what information you want to extract
// For example: sprintf(reportStr, "Element Type: %s, GUID: %s", ...);
outFile << reportStr << std::endl;
}
}
Initialization:
// Initialize function
GSErrCode __ACENV_CALL Initialize(void) {
GSErrCode err = ACAPI_MenuItem_InstallMenuHandler(AddOnMenuID, MenuCommandHandler);
// Open the output file for writing
outFile.open("ElementInfo.txt");
return err;
}
// Output file for element information
std::ofstream outFile;
Regards...
2023-12-21 02:07 AM
Your message is not clear as to what information you are trying to export but I suspect that you "are trying to reinvent the wheel".
Specificity what elements do you need info from? Not all elements have much info available, i.e. MEP elements (YET)? Do want to see materials, GUID, custom properties or certain "built-in" properties? if so, which ones" And do you want to export to a CSV file, Excel SS, or a dialog or all or just selectable?
This is all just a basic Python script, although some certain info may also require a ADD In as in getting the parameters from GDL objects. The good part is that this completely free with Python which has those capabilities built-in, including access (read/write) to CSV text files, Excel files and user dialogs. The plus side is that you , most likely, will not have to recompile your addon, or maybe even need a addon, with every release of Archicad. Most scripts today work across versions from 25 onward. If you care to give some specific details, I could provide more guidance and/or perhaps a preliminary demo script and video.
2023-12-22 01:16 AM
@poco2013 Thank you very much for the suggestion.
I'm currently engaged in a project involving the ArchiCAD C++ API and have come across a specific challenge related to dimension elements. My task involves determining which architectural elements (such as walls, slabs, etc.) are associated with a given dimension element.
While I have successfully managed to extract basic properties of dimensions and write this information to a text file, my current hurdle is in understanding how to identify the building elements these dimensions are attached. I'm utilizing the API_DimensionType structure for accessing properties of the dimensions, but the process of finding links or references to the actual elements they're attached to isn't clear to me.
Any advice or suggestions on this aspect within the ArchiCAD C++ API would be greatly appreciated.
Thank you for your help!