Archicad C++ API
About Archicad add-on development using the C++ API.
SOLVED!

Code to select elements in Archicad by GUIDs from clipboard

SajW
Participant
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.
 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).neigID = APINeig_Wall;
		(*selNeig).guid = selection;
	}

	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));
}
1 ACCEPTED SOLUTION

Accepted Solutions
Solution
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
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:

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:
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).guid = APIGuidFromString (guidStrings.ToCStr ().Get ());
	}

	GSErrCode err = ACAPI_Element_Select (neigs, count, true);
	BMKillHandle (reinterpret_cast<GSHandle*> (&neigs));
	return err;
}

View solution in original post

9 REPLIES 9
Solution
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
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:

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:
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).guid = APIGuidFromString (guidStrings.ToCStr ().Get ());
	}

	GSErrCode err = ACAPI_Element_Select (neigs, count, true);
	BMKillHandle (reinterpret_cast<GSHandle*> (&neigs));
	return err;
}
SajW
Participant
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).guid = APIGuidFromString (guidStrings.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?
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
SajW wrote:
Thanks for this code, but I am having trouble calling this function.. How do I call it?

Simply call it this way:
// 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).
SajW
Participant
This code does not work for me.. does nothing.. were you able to test it?
I have tried to call the function but does not work. Can you explain about the return type of the calling.
SajW
Participant
 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
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
SajW wrote:
I have tried to call the function but does not work.
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?
SajW
Participant
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
SajW
Participant
Tibor wrote:

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.
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
I recommend you this new blog post at our API Site:
http://archicadapi.graphisoft.com/browser-control-and-javascript-connection
Especially the video in it demonstrates something similar what you wanted to implement (select element by GUID from clipboard):
https://ttprivatenew.s3.amazonaws.com/pulse/lorantfyt/attachments/11509975/browser_control_example.m...