We value your input! Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey
2023-07-11 09:58 PM - edited 2023-07-11 09:59 PM
WIN 10 | AC24 | VS2017
I am writing an add-on to scan all links, inspect external file names, and capture instances where a .bpn file has been linked in or a file from another project folder has been linked in. I am starting with something from the ..\Examples\Database_Control folder.
In Database_Control.cpp there is:
// -----------------------------------------------------------------------------
// Dump info for drawing links in the current database
// -----------------------------------------------------------------------------
static void Do_ListDrawingLinks ()
{
...
I have modified it slightly to change the DBPrintf() statements to be ACAPI_WriteReport() statements. This function now reads:
static void Do_ListDrawingLinks()
{
GSErrCode err = NoError;
GS::IntPtr store = 1;
err = ACAPI_Database(APIDb_StoreViewSettingsID, (void *)store);
if (err != NoError) {
store = -1;
err = NoError;
}
API_DatabaseInfo currentDB;
BNZeroMemory(¤tDB, sizeof(API_DatabaseInfo));
ACAPI_Database(APIDb_GetCurrentDatabaseID, ¤tDB);
GS::Array<API_Guid> drawingList;
if (ACAPI_Element_GetElemList(API_DrawingID, &drawingList) != NoError) {
ACAPI_WriteReport("Error in ACAPI_Element_GetElemList ().", true);
return;
}
for (auto& guid : drawingList.AsConst()) {
API_Element elem = {};
elem.header.guid = guid;
err = ACAPI_Element_Get(&elem);
char buffer[128];
ACAPI_WriteReport(itoa(err, buffer, 10), true);
if (err != NoError) {
//DBPrintf("DatabaseControl :: Do_ListDrawingLinks :: Cannot get Drawing with GUID %s.\n", APIGuidToString(guid).ToCStr().Get());
ACAPI_WriteReport(GS::UniString::Printf("DatabaseControl :: Do_ListDrawingLinks :: Cannot get Drawing with GUID %s.\n", APIGuidToString(guid).ToCStr().Get()), false);
ACAPI_WriteReport("Error in ACAPI_Element_GetElemList ().", true);
continue;
}
API_DrawingLinkInfo drwLinkInfo;
err = ACAPI_Database(APIDb_GetDrawingLinkID, (void*)(&(elem.header.guid)), &drwLinkInfo);
ACAPI_WriteReport(itoa(err, buffer, 10), true);
if (err != NoError) {
DBPrintf("DatabaseControl :: Do_ListDrawingLinks :: Cannot get link information for Drawing with GUID %s.\n", APIGuidToString(guid).ToCStr().Get());
ACAPI_WriteReport(GS::UniString::Printf("DatabaseControl :: Do_ListDrawingLinks :: Cannot get link information for Drawing with GUID %s.\n", APIGuidToString(guid).ToCStr().Get()), false);
if (drwLinkInfo.linkPath != nullptr)
delete drwLinkInfo.linkPath;
if (drwLinkInfo.viewPath != nullptr)
BMKillPtr(&(drwLinkInfo.viewPath));
continue;
}
//DBPrintf("\tlink No. %ld :", elem.drawing.linkUId);
ACAPI_WriteReport(GS::UniString::Printf("\tLink No. %ld :", elem.drawing.linkUId), false);
if (drwLinkInfo.linkPath != nullptr) {
//DBPrintf("\t%s", drwLinkInfo.linkPath->ToDisplayText().ToCStr().Get());
ACAPI_WriteReport(GS::UniString::Printf("\t%s", drwLinkInfo.linkPath->ToDisplayText().ToCStr().Get()), false);
delete drwLinkInfo.linkPath;
}
else
{
ACAPI_WriteReport("drwLinkInfo.linkPath == nullptr", false);
}
if (drwLinkInfo.viewPath != nullptr)
BMKillPtr(&(drwLinkInfo.viewPath));
if (drwLinkInfo.linkTypeID == API_DrawingLink_InternalViewID)
{
ACAPI_WriteReport("IS internal link type...", false);
//DBPrintf("\t (internal %s, guid: %s)", (drwLinkInfo.viewType == API_ViewNodePerspective || drwLinkInfo.viewType == API_ViewNodeAxonometry) ? "3D view" : "view", APIGuidToString(drwLinkInfo.linkGuid).ToCStr().Get());
ACAPI_WriteReport(GS::UniString::Printf("\t(0) (internal %s, guid: %s)", (drwLinkInfo.viewType == API_ViewNodePerspective || drwLinkInfo.viewType == API_ViewNodeAxonometry) ? "3D view" : "view", APIGuidToString(drwLinkInfo.linkGuid).ToCStr().Get()), false);
}
else
{
ACAPI_WriteReport("NOT internal link type...", false);
}
if (drwLinkInfo.linkTypeID == API_DrawingLink_ExternalViewID)
{
//DBPrintf("\t (internal %s, guid: %s)", (drwLinkInfo.viewType == API_ViewNodePerspective || drwLinkInfo.viewType == API_ViewNodeAxonometry) ? "3D view" : "view", APIGuidToString(drwLinkInfo.linkGuid).ToCStr().Get());
ACAPI_WriteReport(GS::UniString::Printf("\t(1) (external %s, guid: %s)", (drwLinkInfo.viewType == API_ViewNodePerspective || drwLinkInfo.viewType == API_ViewNodeAxonometry) ? "3D view" : "view", APIGuidToString(drwLinkInfo.linkGuid).ToCStr().Get()), false);
}
else
{
ACAPI_WriteReport("NOT external link type...", false);
}
API_DatabaseInfo dbInfo;
BNZeroMemory(&dbInfo, sizeof(API_DatabaseInfo));
dbInfo.typeID = APIWind_DrawingID;
dbInfo.linkedElement = elem.header.guid;
err = ACAPI_Database(APIDb_ChangeCurrentDatabaseID, &dbInfo);
ACAPI_WriteReport(itoa(err, buffer, 10), true);
if (err == NoError) {
GS::Array<API_Guid> elemList;
ACAPI_Element_GetElemList(API_LineID, &elemList);
//DBPrintf("\t(number of lines = %ld,", elemList.GetSize());
ACAPI_WriteReport(GS::UniString::Printf("\t(number of lines = %ld,", elemList.GetSize()), false);
short visible, onStory, inView;
visible = onStory = inView = 0;
for (auto& elemGuid : elemList.AsConst()) {
if (ACAPI_Element_Filter(elemGuid, APIFilt_OnVisLayer))
++visible;
if (ACAPI_Element_Filter(elemGuid, APIFilt_OnActFloor))
++onStory;
if (ACAPI_Element_Filter(elemGuid, APIFilt_InCroppedView))
++inView;
}
//DBPrintf("%d visible, %d on the view\'s floor, %d in the cropped view", visible, onStory, inView);
ACAPI_WriteReport(GS::UniString::Printf("%d visible, %d on the view\'s floor, %d in the cropped view", visible, onStory, inView), false);
// Switch back to the original database, because APIDb_ChangeCurrentDatabaseID tries to fetch the drawing element
// from the layout's database internally
ACAPI_Database(APIDb_ChangeCurrentDatabaseID, ¤tDB);
}
else
{
ACAPI_WriteReport(itoa(err, buffer, 10), true);
}
//DBPrintf("\n");
ACAPI_WriteReport("\n", false);
//DBPrintf("\tName: %s", drwLinkInfo.name);
ACAPI_WriteReport(GS::UniString::Printf("\tName: %s", drwLinkInfo.name), false);
//DBPrintf("\n");
DBPrintf("\n", false);
//DBPrintf("\tNumber %s", drwLinkInfo.number);
ACAPI_WriteReport(GS::UniString::Printf("\tNumber %s", drwLinkInfo.number), false);
//DBPrintf("\n");
ACAPI_WriteReport("\n", false);
short userId = 0;
if (ACAPI_Database(APIDb_GetTWOwnerID, &(dbInfo.databaseUnId), &userId) == NoError)
//DBPrintf("\tTeamWork owner ID: %d\n", userId);
ACAPI_WriteReport(GS::UniString::Printf("\tTeamWork owner ID: %d\n", userId), false);
}
if (store == 1) {
store = 0;
ACAPI_Database(APIDb_StoreViewSettingsID, (void *)store);
}
}// Do_ListDrawingLinks
This is basically as-is, straight from the ..\Examples folder.
However, I am getting an error with the second to last line:
err = ACAPI_Database(APIDb_ChangeCurrentDatabaseID, &dbInfo);
if (drwLinkInfo.linkTypeID == API_DrawingLink_ExternalViewID)
{
//DBPrintf("\t (internal %s, guid: %s)", (drwLinkInfo.viewType == API_ViewNodePerspective || drwLinkInfo.viewType == API_ViewNodeAxonometry) ? "3D view" : "view", APIGuidToString(drwLinkInfo.linkGuid).ToCStr().Get());
ACAPI_WriteReport(GS::UniString::Printf("\t(1) (external %s, guid: %s)", (drwLinkInfo.viewType == API_ViewNodePerspective || drwLinkInfo.viewType == API_ViewNodeAxonometry) ? "3D view" : "view", APIGuidToString(drwLinkInfo.linkGuid).ToCStr().Get()), false);
}
else
{
ACAPI_WriteReport("NOT external link type...", false);
}
API_DatabaseInfo dbInfo;
BNZeroMemory(&dbInfo, sizeof(API_DatabaseInfo));
dbInfo.typeID = APIWind_DrawingID;
dbInfo.linkedElement = elem.header.guid;
err = ACAPI_Database(APIDb_ChangeCurrentDatabaseID, &dbInfo);
ACAPI_WriteReport(itoa(err, buffer, 10), true);
And my [ACAPI_WriteReport(itoa(err, buffer, 10), true);] produces this:
which translates to this:
Any idea what I should be looking for?
Thanks to all - Chris
2023-07-13 08:53 PM
After a little more research, I realize the part of the code producing the error is not needed for what I want to do, so <Delete>...
I am able to successfully capture the full path of an external linked file for .dwg and .pdf files.
========================
Number of Drawings: 10
========================
Y:\2020\2020063\Drawings\Design\20210514-Midtown_Civil Bases.dwg
Y:\2020\2020063\Drawings\Consult\Interiors\20211130_Permit Backgr...
For .jpg files, I am trying the similarly formatted code I used above for .dwg and .pdf files,
//
// Pictures
//
GS::Array<API_Guid> picList;
if (ACAPI_Element_GetElemList(API_PictureID, &picList) != NoError) {
ACAPI_WriteReport("Error in ACAPI_Element_GetElemList ().", true);
return;
}
else
{
ACAPI_WriteReport("========================", false);
ACAPI_WriteReport("Number of Pictures: " + GS::UniString(itoa(picList.GetSize(), buffer, 10)), false);
ACAPI_WriteReport("========================", false);
}
for (auto& guid : picList.AsConst()) {
API_Element picElem = {};
picElem.header.guid = guid;
err = ACAPI_Element_Get(&picElem);
if (err != NoError) {
ACAPI_WriteReport(GS::UniString::Printf("\tDatabaseControl :: Do_ListDrawingLinks :: Cannot get Drawing with GUID %s.\n", APIGuidToString(guid).ToCStr().Get()), false);
ACAPI_WriteReport("Error in ACAPI_Element_GetElemList ().", true);
continue;
}
With this code, I am able to get the collection of pictures and the collection of details, as verified by .GetSize() data.
========================
Number of Pictures: 76
========================
========================
Number of Details: 88
========================
But, with this code, I am not able to get full path of each.
========================
Number of Pictures: 76
========================
DatabaseControl :: Do_ListDrawingLinks :: Cannot get link information for Drawing with GUID 275B9808-DB9E-4370-8446-8FF6A8F9A991.
DatabaseControl :: Do_ListDrawingLinks :: Cannot get li
...
I am using the appropriate member of the API_ElemTypeID structure.
The APIDb_GetDrawingLinkID used for drawings does not translate well to pictures [APIDb_GetPictureLinkID] or details [APIDb_GetDetailLinkID].
What can I use in the place of APIDb_GetDrawingLinkID to get full paths of pictures and details?
thanks - chris