Sep 6, 2012

Fun with the memoQ 6 Client API!

The release of Build 55 of memoQ version 6 included a client application programming interface (API) for the first time. It is currently available only in the project manager edition of memoQ, which is really a shame, but I look at this as a good start nonetheless. I have wanted this API for years, and a mere 6 months before it was released Kilgray's chief developer swore that it would never happen, because the work involved was monumental and the effort had no perceived payoff. Well, events unanticipated on that cold February night in Budapest changed that perception, and this is an excellent start for a great tool that was never supposed to happen. The current scope is pretty much limited to project preparation, analysis and TM manipulation, but even there much can be found to simplify the lives of some translators and corporate users with automation.

A simple snippet of script code for exporting a TM to TMX has been circulating for a while now as a VBA macro to run from Microsoft Word, for example. Personally, I object to running something in MS Word that has nothing to do with that program, so I recoded it as an executable script and added a few extra tweaks:
tmFolder = InputBox("Which TM should be exported?")
if tmFolder <> "" then

' The path where all my memoQ TMs are stored
standardTMpath = "C:\ProgramData\MemoQ\Translation Memories\"

'build absolute paths
outputTMXfile =  ".\" & tmFolder & "_" & date() & ".tmx"
tmFolder = standardTMpath & tmFolder

Set fact = CreateObject("MemoQ.ClientService.ServiceFactoryScripting")
Set tmService = fact.CreateTMService
Set createTMRes = tmService.ExportToTMX(tmFolder, outputTMXfile)
if createTMRes.Success = False then
   MsgBox createTMRes.ShortErrorMessage
   MsgBox "The TM was exported."
end if

end if
Just copy that script into a text file, rename the extension to *.vbs and you have a double-clickable script to export a TM without opening memoQ. The TMX export is placed in the same folder where the script is executed and tagged with the date of the export.

Encouraged by this little test, I went on to tackle one of my pet peeves: the lack of muliti-file import capabilities in memoQ TMs. Trados Studio has no problem importing a folder full of TMX files to a TM in one go, but with memoQ one must import each TMX file - painfully - one at a time. The pain is felt quite severely if, for example, you are a former OmegaT user with a legacy of 300+ TMX files from your old projects.

So I wrote another little script which allows me to drag and drop any number of TMX files onto its icon and have them all import to the specified TM. This is a rather crude example for just one set of had-coded sublanguages (DE-DE and EN-US). The API currently does not allow sublanguages to be ignored for the import. Adapt this to use your relevant sublanguages if you like:
' memoQ TMX import macro
' drag & drop TMX files onto the script icon
tmFolder = InputBox("To which TM should the TMX file(s) be imported?")
If tmFolder <> "" Then

' The path where all my memoQ TMs are stored
standardTMpath = "E:\Working databases\MemoQ\TMs\"

'build absolute path
tmFolder = standardTMpath & tmFolder

' Create the ServiceFactoryScripting object and TM service
Set objSFS = CreateObject("MemoQ.ClientService.ServiceFactoryScripting")
Set svcTM = objSFS.CreateTMService

' Set import options parameters
Set objImportOptions = CreateObject("MemoQ.ClientService.TMImportOptionsScripting")
objImportOptions.TMXSourceLanguageCode = "ger-de" 
objImportOptions.TMXTargetLanguageCode = "eng-us"  
objImportOptions.TradosImportOptimization = False
objImportOptions.DefaultValues = Null
objImportOptions.DefaultsOverrideInput = False

  Set objArgs = WScript.Arguments
  For I = 0 To objArgs.Count - 1
    tmxfile = objArgs(I)
    logFileName = tmFolder & "_" & date() & "_" & "importlog." & I & ".txt"

    Set returnvalue = svcTM.ImportFromTMX(tmFolder, tmxfile, objImportOptions, logFileName)
    If returnvalue.Success = False Then
        MsgBox returnvalue.ShortErrorMessage
        MsgBox "No errors in the import of " & tmxfile & ". See the log file at: " & logFileName
    End If

end if

Since I once wasted a full day importing a big load of TMX files to memoQ (before I got the bright idea to use The Other Tool as an intermediate step), I was so delighted to get this script working that I just kept making new test TMs and running it long past the point where there was anything left to prove. It's just a thrill to know that consolidating my TMs is now much, much simpler!

These are just a few of the myriad simplifications that are possible for one's processes with the new API. I expect most of its applications will be in "real" programs with real programmers using "real" languages and not wimpy, half-baked scripts like I've thrown together and shown here. This API has potential benefits to a great number of ordinary memoQ users, I think - especially if little productivity tips like these here are shared. So I do hope that, at some point, access to the client API is expanded to include the memoQ Translator Pro edition!


  1. Hi, How did you manage to register the dll? I tried regasm.exe, which seemed succesful, but then again, I receive an error "Can't add reference to the specified dll". Thanks in advance,

  2. I realize this is pretty old post, but I'm pretty desperate...
    I'm experimenting with MemoQ 2015 client API and I'm stuggling with using methods requiring "array of strings" as parameter, e.g. the "sourceFiles" parameter for GetStatusReport or Analyze methods.
    I simply don't understand how should this parameter look like... :(
    Standard VBScript array (e.g. Files = Array ("C:\foo\bar.mqxlz") ) doesn't work.
    Simple string (Files = "C:\foo\bar.mqxlz") doesn't work either...
    I always get Microsoft VBScript runtime error: Invalid procedure call or argument: 'GetStatusReport'

    The client API documentation is useless, it's apparently written for .NET developers... it seems to me that Kilgray developers didn't test the COM scripting in real life scenarios at all :(

  3. Haven't look at this stuff in a while so I'm a bit rusty. With the new scripting features of memoQ 2015 some of what I used to do with this API is no longer necessary. Have you contacted Support? Rattling the cage a bit over the API documentation and examples is not a bad idea, as they do need attention.....

  4. Yes, I have contacted support, but they have not replied yet... and god knows how long it will take them to reply.
    Regarding the documentation - that's the point, I've been through the doc completely, but as I said, it's so freaking .NET-ish that for us oldschool batch scripting guys it's totally useless. All those classes and interfaces and sh*t... it's all Greek to me :(
    Just look in %ProgramData%\MemoQ\SDK\ and see for yourself...

    Another thing I contacted support with is that the COM API doesn't work in JScript :(
    Even the example code from the memoQ.ClientService.Guide PDF converted to JScript doesn't work...
    It shows exactly the same symptoms as this guy describes:
    But unlike him, we can't make change to the MemoQ source code, so we are screwed...

    It all looks to me that the Kilgray devs did a VERY poor job here...

    1. Well, if you know the backstory to this one, it's almost forgivable. Kilgray never wanted to make a client API, but it was required for that EU tender a few years ago, and its scope is tailored to that of the tender requirements at the time. However, now that it exists, I think it is worth improving, expanding and making available for the TP edition for reasons that are fairly obvious I think. Start campaigning and maybe in a few years we'll see a result....

    2. For the record...
      Kilgray support replied that they "have managed to find the root cause of the JScript problem, and fixed our client API. The next version of the memoQ client will contain the modified API dll."

      For the VBScript problem there is "workaround" in using different construct for the array variable:

      Dim Files(1)
      Files(0) = "D:\test\foo.mqxlz"
      Files(1) = "D:\test\bar.mqxlz"
      Set result = service.GetStatusReport(Files)

      This works as well:
      Set result = service.GetStatusReport(Array("D:\test\foo.mqxlz", "D:\test\bar.mqxlz"))

      They still have to investigate why the following construct doesn't work:
      Files = Array("D:\test\foo.mqxlz", "D:\test\bar.mqxlz")
      Set result = service.GetStatusReport(Files)


Notice to spammers: your locations are being traced and fed to the recreational target list for my new line of chemical weapon drones :-)