Using aaApi_CopyDocument and aaApi_UpdateLinkDataColumnValue

Hello,

I'm working through an issue that involves copying a document and then updating the attributes on that document based on a form that a user has filled out. Below is how I'm using the copy function:

bCreateDocSuccess = aaApi_CopyDocument(SourceProjectIDVector[i], SourceDocumentIDVector[i], TargetProjectIDVector[i], &NewDocumentID, NULL, m_sFileName[i], m_sName[i], m_sDescription[i], AADMS_DOCCOPY_CAN_OVERWRITE);

Here is a larger example of how I'm trying to update the attributes:

aaApi_FreeLinkDataUpdateDesc();

aaApi_UpdateLinkDataColumnValue(lTableId, lColId, m_sAttributes[fileNum][0]);

LONG AttrSheetlRowCount = 0;
AttrSheetlRowCount = aaApi_SelectLinkDataByObject(lTableId, AADMSLDT_DOCUMENT, TargetProjectIDVector[0], CopiedDocumentID, NULL, &lCount, lCols, NULL);

for (LONG i = 0; i < AttrSheetlRowCount; i++) {
	CString strAttrColValue;
	strAttrColValue.Format(_T("%s"), aaApi_GetLinkDataColumnValue(i, 0));
	LONG lAttribShtId = _wtol(strAttrColValue);
	aaApi_UpdateEnvAttr(lTableId, lAttribShtId);
}

The file is copied correctly and to the correct location. However, the issue comes when there are no attributes on the file. None that the user entered and none copied from the old file. I think I've narrowed the issue down to something to do with an "Attribute Sheet" not being created for the new document. The SDK seems to do some automagic and create one if I use the document copy flag "AADMS_DOCCOPY_ATTRS". I think a good starting point would be a little help explaining what an attribute sheet is and how it relates to a document. Let me know if you need me to explain anything else in more detail.

Thanks in advance!

ProjectWise Explorer Version 10.00.03.167

ProjectWise SDK Version 08.11.11559

ProjectWise Server Version ???

  • Geoffrey,

    This is a bit awkward for me because one of the first things I mention when someone wants to take the PW SDK training is to ask about their experience with ProjectWise, both as a user, and as an Administrator.  My spin on this is that you really shouldn't be trying to customize something that you don't understand.  Hopefully, you will spend some "quality time" with ProjectWise in the near future and get familiar with its features, etc.

    In the meantime, "attributes" are the properties that you can assign values to that are inside of a ProjectWise Environment.  OK, "words get in the way" again.  "attribute" is used in more than one context in the ProjectWise SDK help, so basically, the attributes in the context that you are asking about are the values for each of the columns in the database table associated with the ProjectWise environment used by the document's folder.  And an "attribute sheet" is a row in the environment table associated with a specific document. Most users expect just one row (attribute sheet) for a given document, but in reality, you can have zero, one, or more "attribute sheets" for a given document.

    It gets a bit complicated because there are some "rules" involved, some of which are NOT enforced by the APIs, that's your job as a developer to inspect the relevant user and datasource settings and apply them as appropriate for you needs.  There are some settings that can be set by a ProjectWise Administrator on an environment that relate to "what to do when" a document is created or copied.  The setting "Create attribute records upon document creation" is just that, a setting.  ProjectWise Explorer honors that setting, but it is up to you, the developer to check to see if it is set, and then whether or not you should also honor it.  Same for the settings on each attribute in an environment, i.e. "Copied inside document", "Copied inside environment", and "Copied or moved from other environment".  That last one can be a bit "tricky" because you, the developer, have to determine if an attribute in the source matches an attribute in the target.  Attribute labels are what the user sees in ProjectWise Explorer, but as a developer, you only care about attribute table and column ids, so you have to have a way (some logic) to "match them up", etc.

    I also like to say in the training class, that some things in ProjectWise that you think would be easy at the API level, are not, and other things that might think would be difficult are not, but you don't to choose which ones are "easy" or  "non-trivial"!  Again, you as a developer, need to understand what ProjectWise is doing as it is configured for the specific user, as well as for the specific datasource, and then code appropriately.  Security and some user settings are enforced at the API level, but many settings are only enforced by the developer of the application in use.  ProjectWise Explorer interprets these settings, well because that's the primary client, but the API allows other developers to interpret those "rules" as they deem appropriate.

    I would suggest determining what "your" rules need to be when copying a document from one folder to another, especially if the source and target folders' environments are different, as well as what to do with the values in the attributes (copy, clear, or use some default value?).  And you may also want to consider if you need to make your "rules" configurable or not, and then how you would implement that, etc.

    If you are simply "mimicking" what ProjectWise Explorer would do, then you need to retrieve the values for the relevant settings and implement code to do what ProjectWise Explorer would do.  As for copying a document to a different folder with the same environment, you will have to create the first "attribute sheet", or any others that you deem necessary.  When you copy a document from one folder to another (excluding when versioning may be involved!), then you will not be updating any existing attribute sheets, well because there aren't any (yet)!

    My apologies if my response seems condescending in any sense.  My intent is only to emphasize what I mention in the PW SDK training class.  It isn't uncommon to have a programmer "assigned" to take the training, but not given the appropriate ProjectWise user and administrator training, which makes it much harder not only to teach the class, but I think is a bit "unfair" to the programmer taking the class!

    In any case, eventually the goal is to get the PW SDK training "online".  For now, I've included the solution .cpp file for one of the exercises in the course for dealing with "attributes".  You can take a look at the code and then you should be able to determine the general flow/logic of creating a new attribute sheet (row).  I've also included the exercise instructions so that you can relate what the code is doing as it relates to the way it was implemented.

    https://communities.bentley.com/cfs-file/__key/communityserver-discussions-components-files/342995/MyAttributes01.cpp

    PDF

    Another approach you might consider is to take a look at MostOfDavesClasses.cs located here: https://github.com/DaveBrumbaugh/MostOfDavesClasses-CSharp-Wrappers-For-ProjectWise 

    If you look through the various classes and methods, you will find some classes and methods that make dealing with document attributes "easier", at least from a developer's perspective.  If you code with C#, you can obviously use MostOfDavesClasses directly, but if you are coding in C++, you can at least take a look at the calls being made to the native API functions, and the logic being used to take advantage of those API functions.

    Good luck and hopefully my thoughts (and files) will be of some help to you!

    And thank you for including information about what versions of ProjectWise are involved!  As an FYI, you can use the PowerShell module PWPS_DBA to determine the version of a ProjectWise Server.  You do have to sign into the datasource first, but then you just use the Get-PWActiveServerVersion Cmdlet.

  • Thanks for the thorough response Dan. That helped with my understanding of attribute sheets a lot. I used the exercise doc you sent me to make sure the way I structured document attribute updating was correct. I'm following it to a tee and still the document doesn't have the new attributes. This copy is happening within a single data source. When I copy the document if I use the document copy flag "AADMS_DOCCOPY_ATTRS" it will let me add attributes to the document while also bringing over the attributes from the original file (I don't want the latter to happen). If I take this flag out or add the "AADMS_DOCCOPY_NO_ATTRS" flag then no attributes are populated at all. I didn't think those flags should have any bearing on updating attributes since they are being done with two separate actions. I.E.: Create the document with one function THEN update the attributes on the newly created copied document. Based on your response it seems you recommend I make sure I understand how my environment is setup. With my current understanding I don't see a reason this is happening. After posting this I will take a deeper dive into the data source setting to make sure I'm not missing anything. Is there something else I'm misunderstanding with the functions I listed in my original post and the flags I've posted here?

    Thanks in advance

  • Geoffrey,  I often say "words get in the way" in my posts because I'm easily confused by english, my native and only language!  I'm not sure exactly what you are saying about the behavior you see, and the behavior you are expecting.

    If you post your code, or a large enough snippet, along with some screen shots, that might help me better understand the issue you are trying to communicate to me.

    Words again are getting in the way because you say "create the document with one function THEN update the attributes", which is confusing to me because creating a document in PW is in fact always "one function" which never creates the attributes and you cannot UPDATE attributes if there are none.  Now perhaps the API function you are using, i.e. aaApi_CopyDocuments is creating the attributes as part of the call to it, but it really is happening in two separate steps "behind the scenes".  If I understand what you are saying, you are asking aaApi_CopyDocument to create the attributes along with the document because you set the flag AADMS_DOCCOPY_ATTRS, but I strongly suspect that doing so means that it will follow the "rules" (settings) set by the PW Administrator.  And as you mentioned, you need to understand what they are set to as well as what behavior they will force.

    A common method of "making sure that you get what you want", is to use the aaApi_CopyDocument along with the AADMS_DOCCOPY_NO_ATTRS, and then after the document is successfully created without any attributes, then you would CREATE (INSERT) the attributes as a separate step.  This way you know and control what each attribute value will be because you are explicitly setting the values in your code, not relying upon the configured behavior, which of course could change if one or more of those settings are changed at some point in time.

    And I, like a lot of folks, am guilty of not being clear enough in my explanations, etc.  Looking back at my previous post I see this line:

    "As for copying a document to a different folder with the same environment, you will have to create the first "attribute sheet", or any others that you deem necessary."

    It was "clear to me" what I meant, but now I can see how it didn't account for HOW you would create that first attribute sheet, i.e. use the AADMS_DOCCOPY_ATTRS or actually create the attributes in a separate step.  Obviously, in some cases you may want to do it one way, and in other cases, do it another way.

    Answer Verified By: Geoffrey Samples 

  • I want to thank you again for taking the time to make a thorough response to my questions. I agree with the "words get in the way" sentiment. I find that typing out my thoughts is definitely not my strong suite. I think you just nailed what I had been misunderstanding. I have been using aaApi_CopyDocument and I think I don't fully understand what all is going on behind the scenes with it. In my case I use that function then later use aaApi_FreeLinkDataUpdateDesc, aaApi_UpdateLinkDataColumnValue, and aaApi_UpdateEnvAttr to "update" my attributes. However, based on your wording with "CREATE (INSERT)" I think I'm using the wrong functions here. Let me try to summarize what you are saying to make sure I'm understanding it correctly:

    aaApi_CopyDocument is creating a new file which has 0 attributes if you specify AADMS_DOCCOPY_NO_ATTRS or don't define it in your environment. Using the attribute update functions assume you already have an attribute sheet for the document which is why mine isn't working. I'm trying to update non existent attribute sheets.

    Words might be getting in the way here but I want to double check my understanding. Again I can't emphasize enough how much your detailed answers are helping me! Thanks!

  • Yes, your description is correct.  However, if you are updating attributes, you need to specify which row to update, so if there are no existing rows for the document, you should be able to determine that before you attempt to update a specific row that doesn't exist.

    Checking for, and responding to errors is another topic I emphasize in the training.  The general rule (of course), is if a function call can fail, you should check for any failure and respond appropriately. That takes additional time and effort to design and implement as well as to understand what could go wrong, and what you might be able to do about the failure, etc.

    In the exercises I made available, one of the things I try to point out to folks that you should not ASSUME that there is only one row (or any rows!), because it is possible to have zero, one, or more attribute sheets for a given document.  Again, for most users, more than one sheet for a given document is an "error" (human), but if there is more than one row, you can only update one row at a time, and if there aren't any rows, you have to create a row rather than update an existing row.