Posted Sun, 06 Jun 2021 00:31:09 GMT by Jon Weston File IT Solutions Sr Application Developer and RIM specialist
I'm seeing sample code here for updating an existing table row but am wanting to write a new row to the table.  Has anyone done that in c#?
Posted Wed, 09 Jun 2021 10:50:56 GMT by Simon H. Hellmann Toshiba Tec Germany Imaging Systems GmbH IT-Consultant Document Management Solutions
Hi Jon, 

first, you need to create a new table field or get the existing table field from the document like in your existing scenario. 
You can then create new index fields, add them to a new row and add this one to the table field.

See my example: 
 
DocumentIndexField currentField = DocumentIndexField.Create("TABLE_MYFIELD", value);
currentField.IsNull = false;
currentField.ItemElementName = ItemChoiceType.Decimal; //set the itemchoicetype according to what kind of field it is
//creates a new table row and adds the existing field. If you have more than one column, create more fields like the first one and add to this list
DocumentIndexFieldTableRow newField = new DocumentIndexFieldTableRow() { ColumnValue = new List<DocumentIndexField>() { currentField } }; 
// when done with adding fields to the row, add the row to the table field
tableField.Row.Add(newField);
When done with adding rows to the table, just push the fields as usual with document.PutToFieldsRelationForDocumentIndexFields();

Hope this helps. 

Greetings from Germany,
Simon H. Hellmann
DocuWare System Consultant
Posted Thu, 17 Jun 2021 23:24:31 GMT by Jon Weston File IT Solutions Sr Application Developer and RIM specialist
Hi Simon, thank you for the excellently-commented response.  A couple of questions (if you don't mind):

1. For multiple columns do I just add them into the list like this: DocumentIndexFieldTableRow newField = new DocumentIndexFieldTableRow() { ColumnValue = new List<DocumentIndexField>() { codeField, amountField, descriptionField } };

2. When I compile it I get this error: CS1061: 'DocuWare.Platform.ServerClient.DocumentIndexField' does not contain a definition for 'Row' and no extension method 'Row' accepting a first argument of type 'DocuWare.Platform.ServerClient.DocumentIndexField' could be found (are you missing a using directive or an assembly reference?)
The vm I'm working in was created before table fields existed but I've dealt with that before so I added the updated dll's into the web service's bin folder so they're now version 7.3 [SDK_20200602.3] but that didn't help.
Posted Fri, 18 Jun 2021 04:42:28 GMT by Jon Weston File IT Solutions Sr Application Developer and RIM specialist
Update: I just tried it in a vm that has a web service that I know works with table fields (it has several other WebMethods that work with table fields) so I know the dll's are correct and I got the same error.  Here's how I'm declaring tableField:

MyDoc = GetDocumentFromFileCabinetById(conn, "<cabinetGUID>", DocId);
DocumentIndexField tableField = MyDoc.Fields.FirstOrDefault(f => f.FieldName == "GL Account Distribution" && f.ItemElementName == ItemChoiceType.Table);
Posted Fri, 18 Jun 2021 07:28:02 GMT by Simon H. Hellmann Toshiba Tec Germany Imaging Systems GmbH IT-Consultant Document Management Solutions
Hi Jon, 

for 1.)
if you want to add new rows, you need to create a new DocumentIndexFieldTableRow like you wrote. Every column is a DocumentIndexField in the List ColumnValue. Your example works, if codeField, amountField and descriptionField are of type DocumentIndexField.

for 2.)
first, when getting anything you need to work with from the API, including documents, you should always use GetFromSelfRelation(), in the case of your Document, otherwise some attributes might not get loaded:
MyDoc = GetDocumentFromFileCabinetById(conn, "<cabinetGUID>", DocId);
MyDoc = GetDocumentFromSelfRelation();

Second, you are missing one Step, you need to tell your code that your item is actually a table field, otherwise it just assumes you are working with a general DocumentIndexField:
DocumentIndexFieldTable myTableField = (DocumentIndexFieldTable)MyDoc.Fields.FirstOrDefault(f => f.FieldName == "GL Account Distribution").Item;

Hope this helps.

Greetings from Germany,
Simon H. Hellmann
​​​​​​​DocuWare System Consultant
Posted Fri, 18 Jun 2021 21:51:47 GMT by Jon Weston File IT Solutions Sr Application Developer and RIM specialist
Hi Simon,
That helped quite a bit.  Interestingly it didn't like the "MyDoc = GetDocumentFromSelfRelation();" bit at all because it generated an error saying: "CS0103: The name 'GetDocumentFromSelfRelation' does not exist in the current context" so I just commented it out and (after correcting some other errors) it compiles properly.

A couple of notes about the sample code in the kb article:
1. It didn't like ItemChoiceType.Text for the table columns that are Text but it does seem to like ItemChoiceType.String
2. it doesn't like it when you pass the value of a Decimal field without quotations around it

However, when I run it it says "Object reference not set to an instance of an object." and I've paired the web method back to the basics to see if I can figure out what's going on but I can't, so, much as I hate posting the code itself, I can't think of anything else to do:

//get the document
            MyDoc = GetDocumentFromFileCabinetById(conn, "<CabinetGUID>", DocId);
        //MyDoc = GetDocumentFromSelfRelation();

            DocumentIndexFieldTable tableField = (DocumentIndexFieldTable)MyDoc.Fields.FirstOrDefault(f => f.FieldName == "GL Account Distribution").Item;


                       //make the code field
                        DocumentIndexField codeField = DocumentIndexField.Create("GL_AC_CODE", "Test Code");
                        codeField.IsNull = false;
                        codeField.ItemElementName = ItemChoiceType.String; //set the itemchoicetype according to what kind of field it is

                        //make the amount field
                        DocumentIndexField amountField = DocumentIndexField.Create("GL_AC_AMOUNT", "10.00");
                        amountField.IsNull = false;
                        amountField.ItemElementName = ItemChoiceType.Decimal; //set the itemchoicetype according to what kind of field it is

                        //make the description field
                        DocumentIndexField descriptionField = DocumentIndexField.Create("GL_AC_DESCRIPTION", "Test Description");
                        descriptionField.IsNull = false;
                        descriptionField.ItemElementName = ItemChoiceType.String; //set the itemchoicetype according to what kind of field it is

                        //creates a new table row and adds the existing field. If you have more than one column, create more fields like the first one and add to this list
                        DocumentIndexFieldTableRow newField = new DocumentIndexFieldTableRow() { ColumnValue = new List<DocumentIndexField>() { codeField, amountField, descriptionField } };
                        // when done with adding fields to the row, add the row to the table field
                        tableField.Row.Add(newField);
                

        //Due to reference types we can just take the fields list
        //from original provided document object
        DocumentIndexFields updatedTableIndexFields = new DocumentIndexFields()
        {
            Field = MyDoc.Fields
        };
            MyDoc.PutToFieldsRelationForDocumentIndexFields(updatedTableIndexFields);

 
Posted Sat, 19 Jun 2021 07:23:42 GMT by Fabian Kall - left 01.22

Hello Jon, 

Don't omit the call to GetDocumentFromSelfRelation(), especially when you want to work with table fields.
This is probably what is causing your "Object reference not set to an instance of an object.".issue.


This should work:

MyDoc = MyDoc.GetDocumentFromSelfRelation();

Call GetDocumentFromSelfRelation() on the document. 

I'll try to explain:

With the DocuWare API you always retrieve some of the things we are dealing with when configuring DocuWare Systems. You get FileCabinets from an Organization, documents from FileCabinets, sections from documents, etc. 
To do this, you use methods that the API offers. However, in many cases, you are actually not getting the complete "thing", but some kind of lightweight representation of it.
Not all associated attributes are populated. 
In You case, I'm willing to bet that the document's table field is null, even though You can probably see rows in the table field for that document in the webclient.

Calling GetDocumentFromSelfRelation() before that fixes this, and your table field should now be populated.

My best guess is that this is done for performance reasons. Problably to remedy a 1+n problem.

So whenever you have to drill down deep into a document, make sure you have the selfdocument loaded. 

Posted Mon, 21 Jun 2021 17:54:19 GMT by Jon Weston File IT Solutions Sr Application Developer and RIM specialist

Hi Fabian,

IT WORKS! But it wasn't as simple as that.  Here was the rest of the journey:

I changed

MyDoc = GetDocumentFromSelfRelation();

 to MyDoc = MyDoc.GetDocumentFromSelfRelation(); and didn't get an error but I was still getting the

"Object reference not set to an instance of an object" error so I went through and commented out all the lines one-by-one until I found that the error was caused by this line:

DocumentIndexFieldTable tableField = (DocumentIndexFieldTable)MyDoc.Fields.FirstOrDefault(f => f.FieldName == "GL Account Distribution").Item;

I figured that it must be something to do with the field name because the only name I could find to use in the Configurations->Database Fields was "GL Account Distribution" but that doesn't look like a system name and we're always using a field's system name in web services.  A field's system name is usually visible when you click on the field itself, click on 'more options' and then use the 'Database column' value, but unfortunately table fields don't have that display so I took a guess and put underscores between the words and that got me past the "Object reference not set to an instance of an object" error!

Unfortunately, I was still getting an error which is "There was an error generating the XML document.".  I commented-out this line and got rid of the error:

MyDoc.PutToFieldsRelationForDocumentIndexFields(updatedTableIndexFields);

I thought maybe it had something to do with the data I was writing to the table so I zero'd in on the Amount column as potentially being the problem because we'd already established that even though it's a Decimal datatype it still wanted the value passed as a string.  So I changed the ItemChoiceType setting from ItemChoiceType.Decimal to ItemChoiceType.String and everything worked!

tldr; even though a column is a Decimal datatype you still have to treat it like a String

(any chance someone can update the kb article to save others a lot of grief?)

Posted Tue, 22 Jun 2021 07:32:45 GMT by Simon H. Hellmann Toshiba Tec Germany Imaging Systems GmbH IT-Consultant Document Management Solutions
Hi Jon, 

I think you are actually writing to a text field.
I have never encountered this problem and every table I worked with has at least one decimal field.

See my code snippet for putting any value into a decimal field in a table: 
// var data is a string containing the data you want to write to the table field.
if (!Decimal.TryParse(data, out decimal result))
{
    throw new InvalidCastException("Error: value " + data + "is not a decimal!");
}
DocumentIndexField currentField = DocumentIndexField.Create(tableColumn, result);
currentField = DocumentIndexField.Create(tableColumn, result);
currentField.IsNull = false;
currentField.ItemElementName = ItemChoiceType.Decimal;


Greetings from Germany, 
Simon H. Hellmann
DocuWare System Consultant
 
Posted Tue, 22 Jun 2021 17:48:11 GMT by Jon Weston File IT Solutions Sr Application Developer and RIM specialist

Hi Simon,

I'm as surprised as you, but it's most definitely a Decimal column:

The problem I ran into is when I tried to pass the value to the field the way I saw it in the kb article, like this:

DocumentIndexField amountField = DocumentIndexField.Create("GL_AC_AMOUNT", 10);

If I switch the 10 to having quotes around it (ie. pass it as a string) and use ItemChoiceType.String then it's quite happy.  Interestingly, this does work using ItemChoiceType.Decimal:

DocumentIndexField amountField = DocumentIndexField.Create("GL_AC_AMOUNT", Convert.ToDecimal("10"));

You must be signed in to post in this forum.