title: Sending and receiving data via POST in Microsoft Word 2011 for OSX
body: <p>I am trying to port a macro that we have working for MS Word on Windows that uses a website to generate an equation image and returns that image for insertion into a document. The current (working on Windows) call is below. When I use the same call in OSX, I receive an error 429 stating "ActiveX component can't create object".</p>
  
  <pre><code>' Create an xmlhttp object.
  Set w_page = CreateObject("Microsoft.XMLHTTP")
  
  ' Open the connection to the remote server.
  w_page.Open "POST", WebAdd, False
  
  ' Indicate that the body of the request contains form data
  w_page.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
  
  ' Actually send the request and return the data:
  Font_Size = ComboFontSize.Value
  w_page.Send "formula=" &amp; Font_Size &amp; "." &amp; Latex_Str
  </code></pre>
  
  <p>The error is generated on the <code>Set w_page = CreateObject("Microsoft.XMLHTTP")</code> statement. I have tried a couple of alternate methods such as:</p>
  
  <pre><code>Set w_page = CreateObject("MSXML2.ServerXMLHTTP")
  </code></pre>
  
  <p>and</p>
  
  <pre><code>Set w_page = CreateObject("WinHttp.WinHttpRequest.5.1")
  </code></pre>
  
  <p>But the same error is generated. Please help me find the correct way of sending POSTs in OSX Word 2011.</p>
  
  <p>For anybody interested, the project is available on <a href="https://github.com/Engineero/latex_in_word" rel="nofollow noreferrer">GitHub</a>.</p>
  
  <p>Thanks a lot!</p>
  
  <p><strong>EDIT</strong>: I found <a href="https://stackoverflow.com/questions/158633/how-can-i-send-an-http-post-request-to-a-server-from-excel-using-vba">this post</a> that details an option for use with OSX Excel, but I cannot find its analog for OSX Word. Does anybody know of a Word-equivalent to the Excel <code>ActiveSheet.QueryTables</code> that would work for sending POSTs in OSX?</p>
  
  <p><strong>EDIT</strong>: I have made some progress. It looks like you can call external programs through VBA, and all Macs come with Python installed, so I wrote a Python script that uses <code>urllib</code> and <code>urllib2</code> to send the request to the server. The Python file also uses <code>argparse</code> to parse the formula string, fontsize, and web address from the command line.</p>
  
  <p>Now my macro can call my python script with something like:</p>
  
  <pre><code>sCmd = "python " &amp; pyPath &amp; "getURL.py --formula " &amp; Latex_Str &amp; " --fontsize "_
      &amp; Font_Size &amp; " " &amp; WebAdd
  sResult = Shell(sCmd, vbNormalFocus)
  </code></pre>
  
  <p>Where <code>Latex_Str</code> is input by the user through the app, <code>Font_Size</code> is likewise defined by the user, and <code>WebAdd</code> is one of two addresses, depending on whether we are generating the equation or cleaning up temporary files.</p>
  
  <p>What I cannot figure out is how to get VBA to read the return from my Python script (a string with return values from my server that I need in order to later retrieve the image file). The <code>Shell</code> command only seems return a PID number. Can anybody help?</p>
  
  <p><strong>SOLUTION:</strong> I figured it out! I was able to write a Python script to handle the POST request to the server and print its response to stdout. With the help of the community and lots of documentation online, I was then able to call this Python script using AppleScript from VBA with the <code>result = vba.MacScript(command)</code> method. This enabled me to read the stdout from my Python script into a string variable in VBA. My Python script was as follows:</p>
  
  <pre><code># Import the required libraries
  from urllib import urlencode
  from urllib2 import Request, urlopen, URLError, ProxyHandler, build_opener, install_opener
  import argparse
  
  # Set up our argument parser
  parser = argparse.ArgumentParser(description='Sends LaTeX string to web server and returns meta data used by LaTeX in Word project')
  parser.add_argument('webAddr', type=str, help='Web address of LaTeX in Word server')
  parser.add_argument('--formula', metavar='FRML', type=str, help='A LaTeX formula string')
  parser.add_argument('--fontsize', metavar='SIZE', type=int, default=10, help='Integer representing font size (can be 10, 11, or 12. Default 10)')
  parser.add_argument('--proxServ', metavar='SERV', type=str, help='Web address of proxy server, i.e. http://proxy.server.com:80')
  parser.add_argument('--proxType', metavar='TYPE', type=str, default='http', help='Type of proxy server, i.e. http')
  
  # Get the arguments from the parser
  args = parser.parse_args()
  
  # Define formula string if input
  if args.formula:
      values = {'formula': str(args.fontsize) + '.' + args.formula}   # generate formula from args
  else:
      values = {}
  
  # Define proxy settings if proxy server is input.
  if args.proxServ:       # set up the proxy server support
      proxySupport = ProxyHandler({args.proxType: args.proxServ})
      opener = build_opener(proxySupport)
      install_opener(opener)
  
  # Set up the data object
  data = urlencode(values)
  data = data.encode('utf-8')
  
  # Send request to the server and receive response, with error handling!
  try:
      req = Request(args.webAddr, data)
  
      # Read the response and print to a file
      response = urlopen(req)
      print response.read()
  
  except URLError, e:
      if hasattr(e, 'reason'):    # URL error case
          # a tuple containing error code and text error message
          print 'Error: Failed to reach a server.'
          print 'Reason: ', e.reason
      elif hasattr(e, 'code'):    # HTTP error case
          # HTTP error code, see section 10 of RFC 2616 for details
          print 'Error: The server could not fulfill the request.'
          print 'Error code: ', e.code
          # print e.read()
  </code></pre>
  
  <p><a href="https://stackoverflow.com/questions/17052005/returning-result-of-an-external-script-to-vba">This related thread</a> that I started more recently pointed me in the direction of the <code>MacScript</code> command for calling my function and getting a string return, and @CuberChase got me started down the path to writing an external function to handle the call to the server. Thanks a lot!</p>