2025-02-28 10:54 AM
Hi there! I'm trying to replace one BIM Object (which is already available in the Embedded Library) with another BIM Object using the code below. I'm finding the Lib_Part indices of both objects and setting the libInd of the old object to the new object's libInd (element.object.libInd = replacementLibPart.index;).
I'm facing APIERR_REFUSEDCMD error or APIERR_BADPARS error, when the code reaches ACAPI_Element_Change(). No Matter what I try, I'm unable to fix this. Can you please help me fix this?
Please let me know if my approach has any issues.
Thanks in Advance!.
// Function to find an object by name
API_LibPart FindLibPartByName(const char* partName) {
	API_LibPart libPart;
	BNZeroMemory(&libPart, sizeof(API_LibPart));
	GSErrCode err;
	Int32 numLibParts;
	ACAPI_LibraryPart_GetNum(&numLibParts);
	for (Int32 i = 1; i <= numLibParts; i++) {
		BNZeroMemory(&libPart, sizeof(API_LibPart));
		libPart.index = i;
		err = ACAPI_LibraryPart_Get(&libPart);
		char	docuname[256];
		GS::UniString docName = GS::UniString(libPart.docu_UName);
		const char* cString = docName.ToCStr().Get();
		if (err == NoError && strcmp(cString, partName) == 0) {
			return libPart;
		}
	}
	libPart.index = 0; // Return invalid index if not found
	return libPart;
}
// Function to replace all instances of an old object with a new one
GSErrCode BrowserPalette::ReplaceBIMObjects(const char* oldObjectName, const char* newObjectName) {
	// Get current object's library part
	API_LibPart oldLibPart;
	BNZeroMemory(&oldLibPart, sizeof(API_LibPart));
	//Adding oldobjectname's libpart
	oldLibPart = FindLibPartByName(oldObjectName);
	GS::UniString OldLibpartName(oldLibPart.docu_UName);
	API_LibPart replacementLibPart;
	BNZeroMemory(&replacementLibPart, sizeof(API_LibPart));
	replacementLibPart = FindLibPartByName(newObjectName);
	GS::UniString newLibpartName(replacementLibPart.docu_UName);
	if (ACAPI_LibPart_Get(&oldLibPart) == NoError) {
		ACAPI_WriteReport("Found Object: %s", true, OldLibpartName);
		if (ACAPI_LibPart_Get(&replacementLibPart) == NoError) {
			ACAPI_WriteReport("Replacing %s with %s", true, OldLibpartName.ToCStr().Get(), newLibpartName.ToCStr().Get());
			// Update the object's library part reference
			GS::Array<API_Guid> objectList;
			ACAPI_Element_GetElemList(API_ObjectID, &objectList);
			for (const auto& objGuid : objectList) {
				API_Element element;
				BNZeroMemory(&element, sizeof(API_Element));
				element.header.guid = objGuid;
				if (ACAPI_Element_Get(&element) == NoError) {
					if (element.object.libInd == oldLibPart.index) {
						//ACAPI_WriteReport("Found Element: %s", true, element.object.libInd);
						element.object.libInd = replacementLibPart.index; // Replace with new object index
						GSErrCode err = ACAPI_CallUndoableCommand("Change Object",
							[&]() -> GSErrCode {
							return ACAPI_Element_Change(&element, nullptr, nullptr, 0, false);
						});
						
						//GSErrCode err = ACAPI_Element_Change(&element, nullptr, nullptr, 0, true);
						if (err != NoError) {
								ACAPI_WriteReport("Error updating object: %d", true, err);
						}
					}
				}
			}
		}
		else {
			ACAPI_WriteReport("Replacement object %s not found in Embedded Library.", true, newLibpartName.ToCStr().Get());
		}
	}
	return NoError;
	}
Solved! Go to Solution.
2025-03-04 04:12 AM
Hi, When you'd change an object, the index(libInd) only seems not enough. I think you need to set the mask ACAPI_ELEMENT_MASK_SET() as first, and pass the new object memo like:
ACAPI_Element_Change (&element, &mask, &memo, APIMemoMask_AddPars, true);
Please check the API Examples, you can find similar code which is using the command above.
HTH.
2025-03-04 04:12 AM
Hi, When you'd change an object, the index(libInd) only seems not enough. I think you need to set the mask ACAPI_ELEMENT_MASK_SET() as first, and pass the new object memo like:
ACAPI_Element_Change (&element, &mask, &memo, APIMemoMask_AddPars, true);
Please check the API Examples, you can find similar code which is using the command above.
HTH.