• RE: Migrating PDF's and Data to DocuWare-1516295352

    Mark,

    One more point of clarification -- my code does NOT create file cabinets. A FileCabinet object in C# is just a programmatic representation of an existing DocuWare file cabinet. I still had to create all the file cabinets by hand, saving off the XML used to create them as I went along (so I could more quickly create them when ready to go live).

    My code just takes a document that is saved as a file, loads the dwcontrol file alongside it (as indexes), then uploads the file and applies indexes using the DocuWare API routines UploadDocument and EasyUploadSingleDocument (depending on document size). In fact, my code does not show the part where indexes are generated from the dwcontrol file -- that was a different routine. As long as you can load indexes into a DocuWare Document class (in code), you can use whatever indexing scheme you want.

    C# can manipulate the Fortis COM object, too, I just already had the Foxpro code for that. So, you could, if you wanted, use a single C# program that does everything in one flow, one document at at time:
     
    1. Find a the document in Fortis you want to migrate.
    2. Save the document itself as a file to a known location.
    3. Also save the indexes for the documents in memory (as variables in your program)
    4. Establish a connection to DocuWare and get a FileCabinet object instanced, representing the destination for the document.
    5. Upload the document and indexing information to DocuWare, assuming the indexes on the DocuWare cabinet match the indexes on the original DocuWare document.

    If any of this helps you, I am glad! Good luck!

    Thanks,
    Joe Kaufman

     
  • RE: Canon scanner slowdowns after Windows Feature Update

    James,

    Thanks for weighing in. We have been installing Fujitsu scanners and things are going great. Good to know someone else is seeing issues with the Kodak scanners -- hope Kodak figures out the issue!

    Thanks,
    Joe Kaufman
  • RE: Migrating PDF's and Data to DocuWare-1516295352

    Mark,

    To clarify a few things, the methodology I used required pulling all Fortis documents out and placing them in a directory, along with the dwcontrol files containing their indexes. That was one part of this, and it was written in Foxpro against the Fortis COM object. This process also created a Foxpro table with all document information, including file names, Fortis database locations, Fortis document types, and the Fortis document ID.

    Once all the documents and their indexes were in the right place (which you would have to do anyway if you wanted to use Import Jobs), the C#/.NET application put them in the right file cabinets with their indexes. All cabinets involved in the migration had three fields in them so I could back-link them to Fortis:

    Fortis DB Location
    Fortis Document Type
    Fortis Document ID

    In that sense, the process was self-logging because at any point I could query DocuWare's SQL Server database and see how many documents were migrated. But the C# program also logged progress, in the GUI and with summary results at the end. Since this involved creating my own code, I could do whatever I wanted with regard to logging and progress-reporting.

    As for whether or not the code is straightforward, I would say the actual calls to DocuWare were the easier part. More work was put into deciding how to organize the documents and getting the multi-threading working. The calls to DocuWare followed examples already listed in DocuWare online help. Here are examples of the main routines that stored documents to DocuWare and indexed them (same name, UploadFileToFileCabinet, overloaded static methods):
     
            public static Document UploadFileToFileCabinet(FileCabinet fileCabinet, string uploadFile, string[] indexFieldNames, dynamic[] indexValues, bool timestampsAlreadyUTC = false)
            {
                Document indexInfo = new Document();
                indexInfo.Fields = new List<DocumentIndexField>();
                int numIndexFields = Math.Min(indexFieldNames.Length, indexValues.Length);
                string fieldName = "";
                dynamic value = null;
                Type valueType = null;
                for (int i = 0; i < numIndexFields; i++)
                {
                    fieldName = indexFieldNames[i];
                    value = indexValues[i];
                    valueType = ((ObjectHandle)value).Unwrap().GetType();
                    if (valueType.Name.ToUpper() == "STRING")
                    {
                        indexInfo.Fields.Add(DocumentIndexField.Create(fieldName, (string)value));
                    }
                    else if (valueType.Name.ToUpper() == "INT")
                    {
                        indexInfo.Fields.Add(DocumentIndexField.Create(fieldName, (int)value));
                    }
                    else if (valueType.Name.ToUpper() == "DECIMAL")
                    {
                        indexInfo.Fields.Add(DocumentIndexField.Create(fieldName, (decimal)value));
                    }
                    else if (valueType.Name.ToUpper() == "DATETIME")
                    {
                        DateTime timestamp = (DateTime)value;
                        if (!timestampsAlreadyUTC)
                        {
                            // We need to make timestamps UTC (Universal Coordinated Time) for storage in DocuWare, as that is how
                            // all date/time fields are stored in the database.
                            timestamp = timestamp.ToUniversalTime();
                        }
                        indexInfo.Fields.Add(DocumentIndexField.Create(fieldName, timestamp));
                    }
                }
                return UploadFileToFileCabinet(fileCabinet, uploadFile, indexInfo);
            }
    
            public static Document UploadFileToFileCabinet(FileCabinet fileCabinet, string uploadFile, Document indexInfo = null)
            {
                LastError = "";
                try
                {
                    // We will use a standard upload method for smaller files, but the "Easy" version for larger files, otherwise
                    // large file uploads might fail (the "Easy" version is meant for huge file uploads, according to the documentation).
                    int largeFileThresholdInBytes = 10 * 1024 * 1024;    // 10 MB
                    Document uploadedDoc = null;
                    FileInfo fileInfo = new FileInfo(uploadFile);
                    if (fileInfo.Length < largeFileThresholdInBytes)
                    {
                        // Smaller file.
                        uploadedDoc = fileCabinet.UploadDocument(indexInfo, fileInfo);
                    }
                    else
                    {
                        // Larger file.
                        uploadedDoc = fileCabinet.EasyUploadSingleDocument(fileInfo, indexInfo);
                    }
                    return uploadedDoc;
                }
                catch (Exception ex)
                {
                    LastError = ex.Message;
                    return null;
                }
            }

    You need to have the DocuWare API NuGet packages installed for the above code to truly make sense. And of course these routines require helper routines to do things like get a FileCabinet object by file cabinet name, etc. These routines were a mix of using DocuWare API classes and hitting SQL Server directly to gather various GUIDs and such. I can't really post all that without posting the whole code base.

    So, maybe not quite as straightforward as I said.  *smile*  But it all originated from DocuWare Platform (also known as the "SDK" or "REST API") examples. That documentation can be found here:

    https://developer.docuware.com/dotNet_CodeExamples/d25612d7-49fa-4d66-bfcd-67c5591381f7.html

    That's how I came up with most of my code base, and it took a while. Some of that was due to writing routines in both Foxpro and C#, though. If you go with C#/.NET for all of it, and don't worry about multi-threading, it should come together more quickly.

    Let me know if you have specific questions or if the overall outline of how I did things remains unclear!

    Thanks,
    ​​​​​​​Joe Kaufman
  • RE: Migrating PDF's and Data to DocuWare-1516295352

    Mark,

    The import was very fast, mainly because I wrote it as a multi-threaded app that did various document types at the same time (wrote the utility in C#/.NET).

    It actually took longer to get all the documents out of Fortis, which I did via Foxpro and the Fortis COM object. That job, too, could be split up just by running code on two or three workstations (old-fashioned multi-threading.  *smile*)

    I can't really share the multi-threaded nature of the code because that depends on how documents are segmented. But if you need examples of code to upload a document and index it, I can post snippets that might go beyond what is in online documentation.

    How much faster than import files? I recall it being a lot faster, even without multi-threading. But, I didn't spend that much time trying to make the import jobs faster. There are various things you can tweak, I just never saw much performance improvement. That's why I decided to roll my own solution and I never looked back. Plus, we still use parts of the application I wrote for ongoing integrations between DocuWare and our custom-developed apps.

    Good luck!

    Joe Kaufman

  • RE: Canon scanner slowdowns after Windows Feature Update

    Shawn,

    We discovered that even in the Canon software scans would slow down.

    So, we bought a Fujitsu 7160, and it is very speedy and does a nice job. No slowdowns so far for anyone with Feature Update 2004.

    Thanks,

    Joe Kaufman

  • RE: Setting Document Name view REST api

    Not a problem, glad it worked! Interesting scenario, and it is good to know one can force the filename to be the document name in that way!

    Thanks,
    Joe Kaufman
  • Canon scanner slowdowns after Windows Feature Update

    Hello,

    Shot in the dark here, but has anyone else noticed slowdowns in scanning after a scanning workstation is updated to use Windows Feature Update 2004? We have one person here who, after running the update, has scanning operations take a second or two per page where the scanning used to be a continuous stream. When the 2004 feature update is uninstalled, scanning resumes full speed.

    Canon has not been helpful thus far, so it would seem they have not had many (or any) people report a slowdown, but I thought I would try posting here. We are running DocuWare 6.11 on-premise and use Canon scanners such as the DR-6010C.

    Thanks,
    Joe Kaufman

    P.S. As a bonus question, what brand of scanner do other folks use? Anything else in the Canon price point that works as well with DocuWare? Any gotchas (or brands) to avoid in anyone else's experience?
  • RE: Setting Document Name view REST api

    Stephen,

    I believe the name is determined by whichever database field (index) is given the "Document Name" attribute when designing the file cabinet. There can be only one "Document Name" field designated, and when that index is filled in, it becomes the document name.

    What are you placing in the field designated as Document Name? If you set that index (via the API or the web client), does the name then display as you would hope?

    Thanks,
    Joe Kaufman
  • RE: REST API - Logon Issue

    Adriano.

    I am not sure what you have all tried, but it is very possible to login to DocuWare with basic authentication. Check out this post:

    https://support.docuware.com/de-DE/forums/questions-about-usage-and-configuration/cd2c7857-8f41-e911-a967-000d3ab3fe8a

    There are details on how I use Foxpro to access DocuWare (on-premise, version 6.11). 

    Long story short, via Postman, if you do a POST with the URL:

    http://<server>/DocuWare/Platform/Account/Logon?Organization=<org name>&Username=<username>&Password=<password>

    you should see XML representing various DocuWare links -- it means you are authenticated. If you do this POST with some sort of persistent connection/request object (such as MSXML2.ServerXMLHTTP or MSXML2.XMLHTTP on Windows), you can then do additional GETs to access the various API functions.

    Hope this helps!

    Thanks,
    Joe Kaufman

     
  • RE: What date is displayed in the viewer?

    Steve,

    That's a really good question.

    I could not find that date anywhere in the DocuWare database. I checked the base dwdata table, the related _SECT table, and the related _PAGE table. Didn't find anything that matched.

    So, I found the root document as stored in the file system on the DocuWare server. DocuWare stores the actual document in a defined hierarchy, and the file will always have an XML file beside it. In the XML file is a modification time that matches, and it matches the last modification time on the file itself. Since the viewer obviously pulls the document in from it's file-based location, it must get the information from the document as it does so, and displays the last time the document itself was modified/created when it was just a regular old file on disk.

    I am not sure if that date resides anywhere else, and I am not sure if it comes back in the document information class when using the Platform SDK. That means I am not at all sure as to how you could easily pull that date on your own. Hopefully someone more in the know responds with a more thorough answer...

    Thanks,
    Joe Kaufman