The Global ARCHICAD Community

Stay informed. Get help. Share your knowledge.

Discussions about using GRAPHISOFT's tools (API DevKit) for independent software developers

Moderators: Karl Ottenstein, LaszloNagy, ejrolon, Barry Kelly, gkmethy, MOREH Tamas, Akos Somorjai, Ed Brown, Mihály Palenik, Tibor Lorántfy, rmasaki

#297181
Is it possible to select elements in archiCAD by GUID/s from the clipboard? GUIDs will be copied to the clipboard with line breaks.

I have played with the code given in the examples to select walls from excel sheet without a success.
Code: Select all
 static void	Do_SelectWallsFromExcel(void)
{
	DBPrintf("Selecting walls based on Excel document...\n");

	GS::Array<API_Guid> apiguids;
	ACAPI_Goodies(APIAny_GetSelectedElementID, &apiguids);
	GS::Array<API_Guid> selection;

	libxl::Book* book = xlCreateXMLBook();
	if (DBERROR(book == nullptr))
		return;

	IO::Location location;
	IO::fileSystem.GetSpecialLocation(IO::FileSystem::UserDocuments, &location);
	location.AppendToLocal(IO::Name("export.xlsx"));
	GS::UniString filepath;
	location.ToPath(&filepath);

	bool loaded = book->load(UNISTR_TO_LIBXLSTR(filepath));
	if (DBERROR(!loaded))
		return;

	libxl::Sheet* sheet = book->getSheet(0);
	if (DBERROR(sheet == nullptr))
		return;

	for (int i = 0; i < sheet->lastRow(); ++i) {
		GS::Guid xlGsGuid;
		const auto* cellContentPtr = sheet->readStr(i, 0);
		if (cellContentPtr == nullptr)
			continue;

		GSErrCode err = xlGsGuid.ConvertFromString(cellContentPtr);
		if (err != NoError)
			continue;

		API_Guid xlApiGuid = GSGuid2APIGuid(xlGsGuid);
		if (!apiguids.Contains(xlApiGuid))
			continue;
		selection.Push(xlApiGuid);
	}

	book->release();

	USize selCount = selection.GetSize();
	API_Neig** selNeig = (API_Neig**)(BMAllocateHandle(selCount * sizeof(API_Neig), ALLOCATE_CLEAR, 0));
	for (UIndex i = 0; i < selCount; ++i) {
		(*selNeig)[i].neigID = APINeig_Wall;
		(*selNeig)[i].guid = selection[i];
	}

	GSErrCode err = ACAPI_Element_Select(selNeig, selCount, true);
	if (DBERROR(err != NoError))
		DBPrintf("Selection of %d wall(s) failed.\n", selCount);
	else
		DBPrintf("%d walls successfully selected\n", selCount);
	BMKillHandle(reinterpret_cast<GSHandle*> (&selNeig));
}
#297242
Hi SajW,

I can see that you copied this code from the Database_Control example Add-On and you changed few lines.
I don't understand why you made this change:
Code: Select all
GS::Array<API_Guid> apiguids;
// Original line from Database_Control example Add-On:
ACAPI_Element_GetElemList (API_WallID, &apiguids);
// Changed line by SajW:
ACAPI_Goodies (APIAny_GetSelectedElementID, &apiguids);
If you revert this change, then it should work :) Make sure that the Excel table contains the GUIDs of the exisiting placed walls.
SajW wrote:Is it possible to select elements in archiCAD by GUID/s from the clipboard? GUIDs will be copied to the clipboard with line breaks.
Easy peasy ;)
These few lines will do the job for you:
Code: Select all
static GSErrCode	SelectWallsFromClipboard (const GS::UniString& clipboardString)
{
	GS::Array<GS::UniString> guidStrings;
	clipboardString.Split ("\n", GS::UniString::SkipEmptyParts, &guidStrings);

	const USize count = guidStrings.GetSize ();
	API_Neig** neigs = (API_Neig**) (BMAllocateHandle (count * sizeof (API_Neig), ALLOCATE_CLEAR, 0));
	for (UIndex i = 0; i < count; ++i) {
		(*neigs)[i].guid = APIGuidFromString (guidStrings[i].ToCStr ().Get ());
	}

	GSErrCode err = ACAPI_Element_Select (neigs, count, true);
	BMKillHandle (reinterpret_cast<GSHandle*> (&neigs));
	return err;
}
#297445
Code: Select all
static GSErrCode	SelectWallsFromClipboard (const GS::UniString& clipboardString)
{
	GS::Array<GS::UniString> guidStrings;
	clipboardString.Split ("\n", GS::UniString::SkipEmptyParts, &guidStrings);

	const USize count = guidStrings.GetSize ();
	API_Neig** neigs = (API_Neig**) (BMAllocateHandle (count * sizeof (API_Neig), ALLOCATE_CLEAR, 0));
	for (UIndex i = 0; i < count; ++i) {
		(*neigs)[i].guid = APIGuidFromString (guidStrings[i].ToCStr ().Get ());
	}

	GSErrCode err = ACAPI_Element_Select (neigs, count, true);
	BMKillHandle (reinterpret_cast<GSHandle*> (&neigs));
	return err;
}
Thanks for this code, but I am having trouble calling this function.. How do I call it?
#297450
SajW wrote:
Tue May 21, 2019 3:55 am
Thanks for this code, but I am having trouble calling this function.. How do I call it?

Simply call it this way:
Code: Select all
// Get string from clipboard
GS::UniString clipboardString;
Clipboard::GetInstance ().GetUniString (Clipboard::uniTextTypeId, clipboardString);

// Call the function by passing the string from clipboard
SelectWallsFromClipboard (clipboardString);
Update:
After we investigated SajW's issue, we figured it out that Clipboard::uniTextTypeId value should be used as first parameter when calling Clipboard::GetUniString function (and make sure to use the same value if you are using Clipboard::SetUniString function also).
#297639
Code: Select all
 void	Do_SelectWallsFromExcel(void)
{

	 GS::UniString clipboardString;
	 Clipboard::GetInstance().GetUniString(Clipboard::textTypeId, clipboardString);

	// Call the function by passing the string from clipboard
	SelectWallsFromClipboard(clipboardString);

}
I tried to call it inside the Database_control example Do_SelectWallsFromExcel, but I cannot get it working
#297649
I have the values seperated by \n.

however there is this warning,

Severity Code Description Project File Line Suppression State
Warning LNK4099 PDB 'API_c.pdb' was not found with 'ACAP_STATD.lib(ACAPlib.obj)' or at 'C:\Program Files\GRAPHISOFT\API Development Kit 22.3004\Examples\Database_Control\Build\x64\Debug\API_c.pdb'; linking object as if no debug info Database_Control C:\Program Files\GRAPHISOFT\API Development Kit 22.3004\Examples\Database_Control\ACAP_STATD.lib(ACAPlib.obj) 1
#297812
Tibor Lorántfy wrote:
Fri May 24, 2019 8:50 am

Are you sure the clipboard contains GUIDs of existing elements separated by a '\n' character?
When you debug the code, what is the content of the guidString array inside the SelectWallsFromClipboard functions?
Value of guidStrings array is something like this.

[1] ({"㉄㤹䐷ㄹ㈭䘵ⵆ㘴䐳䄭䘸ⵅ㔶㤹㤰㈳㐶㍆湜䔲䕆䄰㘰䔭うⵂ㠴㥅䈭㘲ⴶ㘸䈹䉁䐹㠸"})

I think the clipboard value has been converted to some other characters.