2

this might be a silly question. But I am desperate. I am a math teacher and I try to generate Math tests. I tried Python for this and I get some things done. However, I am not a professional programmer, so I get lost with MathMl, prettyprint() and whatsoever.

Is there anybody who can supply me a complete example that I can execute? It may just contain one small silly equation, that does not matter. I just want to see how I can get it into a Word document. After that, I can use that as a basis. I work on a Mac.

I hope anyone can help me out. Thanks in advance!

Best regards, Johan

Johan
  • 51
  • 4
  • You might want to look into the .odt format, see: https://stackoverflow.com/questions/32755682/how-to-add-math-formulas-in-odt-document-using-odfpy – Papooch Apr 02 '20 at 20:40

2 Answers2

3

This works for me:

from sympy import *
from docx import Document
from lxml import etree

# create expression
x, y = symbols('x y')
expr1 = (x+y)**2

# create MathML structure
expr1xml = mathml(expr1, printer = 'presentation')
tree = etree.fromstring('<math xmlns="http://www.w3.org/1998/Math/MathML">'+expr1xml+'</math>')

# convert to MS Office structure
xslt = etree.parse('C:/MML2OMML.XSL')
transform = etree.XSLT(xslt)
new_dom = transform(tree)

# write to docx
document = Document()
p = document.add_paragraph()
p._element.append(new_dom.getroot())
document.save("simpleEq.docx")
Johan
  • 51
  • 4
1

How about the following. The capture captures whatever is printed. In this case I use pprint to print the expression that I want written to file. There are lots of options you can use with pprint (including wrapping which you might want to set to False). The quality of output will depend on the fonts you use. I don't do this at all so I don't have a lot of hints for that.

from pprint import pprint
from sympy.utilities.iterables import capture
from sympy.abc import x
from sympy import Integral
with open('out.doc','w',encoding='utf-8') as f:
    f.write(capture(lambda:pprint(Integral(x**2, (x, 1, 3)))))

When I double click (in Windows) on the out.doc file, a word equation with the integral appears.

Here is the actual IPython session:

IPython console for SymPy 1.6.dev (Python 3.7.3-32-bit) (ground types: python)

These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
>>> init_printing()

Documentation can be found at https://docs.sympy.org/dev


In [1]: pprint(Integral(x**2, (x, 1, 3)))
3
(
?  2
? x  dx
)
1

In [2]: from pprint import pprint
   ...: from sympy.utilities.iterables import capture
   ...: from sympy.abc import x
   ...: from sympy import Integral
   ...: with open('out.doc','w',encoding='utf-8') as f:
   ...:     f.write(capture(lambda:pprint(Integral(x**2, (x, 1, 3)))))
   ...:

{problems pasting the unicode here, but it shows up as an integral symbol in console}

smichr
  • 16,948
  • 2
  • 27
  • 34
  • 1
    This just outputs `Integral(x**2, (x, 1, 3))` as text. I don't think there is a simple solution for this as .doc files don't support pretty equations and the .docx file structure is rather complicated (it is a zip archive, essentially). A best bet would be to generate a LaTeX markup and then translate that to PDF. – Papooch Apr 02 '20 at 20:28
  • 1
    https://groups.google.com/forum/#!topic/python-docx/nQfRAZc80Co this could help a bit – Papooch Apr 02 '20 at 20:35
  • 1
    If it looks like `Integral(...)` then unicode pretty printing was not initialized. You should see an actual integral sign and superscript 2 on the x. – smichr Apr 02 '20 at 22:09
  • 1
    Thank you both for your time and effort. The first suggestion does not do it for me. In Word the equation does not look nice. Meanwhile I tried something with MathML and I got something small actually working. – Johan Apr 04 '20 at 16:34