org-mode-ox-odt icon indicating copy to clipboard operation
org-mode-ox-odt copied to clipboard

For #+ATTR_ODT: :list-table t whether the table can be run directly in org-mode to get the table image?

Open Prague2049 opened this issue 2 years ago • 11 comments

For #+ATTR_ODT: :list-table t whether the table can be run directly in org-mode to get the table image? For example, we can generate an image in org mode with the following python code: #+begin_src python :results output #+end_src

Prague2049 avatar Feb 21 '23 10:02 Prague2049

Can you give me some idea of

  • what is the input to the python code block?
  • what is the output from the python code block?
  • when you say image, do you want something like a screenshot of a Table in ODT document.

Essentially, you need to provide more information so that I can make proper recommendation.

If you give examples, with actual figure etc. I can give you the solution right away ....

kjambunathan avatar Feb 21 '23 12:02 kjambunathan

This is an example of generating a table in org-mode using python language. And the image can be displayed in org-mode:

#+begin_src python :session one :exports results :results file import matplotlib.pyplot as plt import numpy as np

ax = plt.subplot(211) rowLabels = ["state", "↑", "↓", "←", "→", "up", "down", "fire"] rowColours = [ "#EBB25E", "#F0C9C0", "#F0C9C0", "#F0C9C0", "#F0C9C0", "#F0C9C0", "#F0C9C0", "#F2F2F2", ]

colColors = ["#377eb8"] colColors.extend(["#00ccff"] * 20)

data = [ [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], ]

column_labels = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", ]

ax.axis("off") ax.table( cellText=data, colLabels=column_labels, colColours=colColors, rowColours=rowColours, rowLabels=rowLabels, cellLoc="center", rowLoc="center", loc="center", )

transpose_data = np.array(data) filename= 'filename.png' plt.savefig(filename) filename #+end_src

#+results: [[file:filename.png]] image

I want to display odt-generated tables in org-mode.

Prague2049 avatar Feb 22 '23 08:02 Prague2049

I don't think there is a easy way to get the rendered table. For the purpose of getting a preview, I have made a command to export a heading with sub-content or a selected region.

(defun my-org-odt-export-heading (arg)
  (interactive "P")
  (save-excursion
    (let ((region-beginning (progn (beginning-of-line)
                                   (outline-previous-heading)
                                   (point)))
          (region-end (if (outline-get-next-sibling)
                          (line-beginning-position)
                          (point))))
      (my-org-odt-export-region region-beginning region-end nil arg))))

(defun my-org-odt-export-region (region-beginning region-end &optional cover-end arg)
  (save-excursion
    (unless cover-end
      (setq cover-end (progn (goto-char 1)
                             (if (and (not (outline-on-heading-p))
                                      (outline-next-heading))
                                 (line-beginning-position)
                                 (point))))))
  (if (<= cover-end region-beginning)
      (let* ((temp-buffer (generate-new-buffer "odt-temp"))
             (cover (buffer-substring-no-properties 1 cover-end))
             (region-text (buffer-substring-no-properties region-beginning region-end)))
        (flet ((buffer-file-name (&optional BUFFER)
                 (concat default-directory "temp.org")))
          (with-current-buffer temp-buffer
            (insert cover)
            (insert region-text)
            (org-odt-export-buffer)
            (and (buffer-name temp-buffer)
                 (if arg (pop-to-buffer temp-buffer)
                     (kill-buffer temp-buffer))))))
      (org-odt-export-to-odt)))

QiangF avatar Feb 22 '23 09:02 QiangF

  1. ODT format allows the first row and first column of a table to be formatted differently

  2. soffice command line executable allows the first page of a odt file to be exported to png or jpeg

(1) requires some minor change elisp change. (I have a protiotype which I will commit soon)

There are multiple ways to achieve 2. Try doing it on a simple table (with colours). I will share recipe for how to add background colors

Message ID: @.***>

kjambunathan avatar Feb 22 '23 16:02 kjambunathan

Use @Qiangf 's suggestion to convert an Org text (or table) to odt file

On Wed, 22 Feb 2023, 1:42 pm Prague2049, @.***> wrote:

This is an example of generating a table in org-mode using python language. And the image can be displayed in org-mode:

#+begin_src python :session one :exports results :results file import matplotlib.pyplot as plt import numpy as np fig, ax = plt.subplots(1, 1) fig, ax = plt.subplots(1, 2)

ax = plt.subplot(211) rowLabels = ["state", "↑", "↓", "←", "→", "up", "down", "fire"] rowColours = [ "#EBB25E", "#F0C9C0", "#F0C9C0", "#F0C9C0", "#F0C9C0", "#F0C9C0", "#F0C9C0", "#F2F2F2", ]

colColors = ["#377eb8"] colColors.extend(["#00ccff"] * 20)

data = [ [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], ]

column_labels = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", ]

ax.axis("off") ax.table( cellText=data, colLabels=column_labels, colColours=colColors, rowColours=rowColours, rowLabels=rowLabels, cellLoc="center", rowLoc="center", loc="center", )

transpose_data = np.array(data) filename= 'filename.png' plt.savefig(filename) filename #+end_src

#+results: [[file:filename.png]] I want to display odt-generated tables in org-mode.

— Reply to this email directly, view it on GitHub https://github.com/kjambunathan/org-mode-ox-odt/issues/240#issuecomment-1439590454, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEXTBKCPK2BYZIAHMQIUZVTWYXC7ZANCNFSM6AAAAAAVC4TLQA . You are receiving this because you commented.Message ID: @.***>

kjambunathan avatar Feb 22 '23 16:02 kjambunathan

Your example uses 5 colors. Such a range of colours is not possible with ODT export.

The attached example uses 2 colors---one for Row Header, and one for Column Header---and the output closely matches what you want. I have also shared recipe for creating png output of a odt table.


I have added two commits as part of this request. So, ensure that you are on https://github.com/kjambunathan/org-mode-ox-odt/commit/6d99b063c3458ae15e22878a6de6b7bf2044c7c0 (which includes the prior commit https://github.com/kjambunathan/org-mode-ox-odt/commit/345cff12b7a611cc701bf07d504e9c7833453300)

Zip file for Demonstration:
issue240.zip

The outputs in the above zip file were created with emacs -Q, and with my libraries loaded. If you are getting a result different from what you see here, it either means (a) you haven't executed the elisp src block within the file or (b) Or your init settings is preventing you from getting the desired results. The solution is (a) emacs -Q and (b) Load odt.el and load ox-odt.el (c) Execute elisp config block in issue240.org (d) Do actual export.

The *Messages* buffer will tell you what is happening behind the scenes


Created /home/kjambunathan/src1/org-mode-ox-odt/testing/examples/odt/issue240/issue240.odt

Executing LANG=en_IN soffice --headless --convert-to png --outdir /home/kjambunathan/src1/org-mode-ox-odt/testing/examples/odt/issue240/ /home/kjambunathan/src1/org-mode-ox-odt/testing/examples/odt/issue240/issue240.odt

convert /home/kjambunathan/src1/org-mode-ox-odt/testing/examples/odt/issue240/issue240.odt -> /home/kjambunathan/src1/org-mode-ox-odt/testing/examples/odt/issue240/issue240.png using filter : writer_png_Export

To get this

issue240

or this

Screenshot from 2023-02-23 14-41-55

do this

#+options: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
#+options: author:nil broken-links:nil c:nil creator:nil
#+options: d:(not "LOGBOOK") date:t e:t email:nil f:t inline:t num:t
#+options: p:nil pri:nil prop:nil stat:t tags:t tasks:t tex:t
#+options: timestamp:t title:t toc:nil todo:t |:t
#+language: en
#+select_tags: export
#+exclude_tags: noexport
#+creator: Emacs 30.0.50 (Org mode 9.6.1)
#+cite_export:

#+ODT_PRETTIFY_XML: ""
# #+ODT_PREFERRED_OUTPUT_FORMAT: jpg
# #+ODT_PREFERRED_OUTPUT_FORMAT: png
#+ODT_PREFERRED_OUTPUT_FORMAT: pdf

* Table output by Python block
:PROPERTIES:
:ATTR_ODT: :page-break "before" :page-style "Landscape"
:END:

#+RESULTS: prettytable
#+ATTR_ODT: :style "GriddedTable"
|       |   1 |   2 |   3 |   4 |   5 |   6 |   7 |   8 |   9 |   10 |   11 |   12 |   13 |   14 |   15 |   16 |   17 |   18 |   19 |   20 |   21 |
|-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+------+------+------+------+------+------+------+------+------+------+------|
| state |   1 |   1 |   1 |   1 |   0 |   0 |   0 |   0 |   0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |
| ↑     |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |
| ↓     |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |
| ←     |   0 |   1 |   0 |   1 |   0 |   1 |   0 |   0 |   0 |    1 |    0 |    1 |    0 |    1 |    0 |    1 |    0 |    0 |    0 |    1 |    0 |
| →     |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |
| up    |   1 |   0 |   1 |   0 |   1 |   0 |   1 |   0 |   1 |    0 |    1 |    0 |    1 |    0 |    1 |    0 |    1 |    0 |    1 |    0 |    0 |
| down  |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    1 |
| fire  |   0 |   0 |   0 |   0 |   0 |   0 |   0 |   1 |   0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    1 |    0 |    0 |    0 |

* Customize ODT
:PROPERTIES:
:ATTR_ODT: :page-break t :page-style "Portrait"
:END:

#+begin_src emacs-lisp :exports code :results none
(set-language-environment "UTF-8")
(require 'ob-shell)
(require 'ob-python)
(setq org-odt-table-cell-variant-calculator nil)
(setq org-confirm-babel-evaluate nil)
(setq org-export-use-babel t)

(cl-pushnew '("GriddedTable" "Custom"
	      ((use-first-row-styles . t)
	       (use-first-column-styles . t)))
	    org-odt-table-styles)

(setq org-babel-load-languages
   '((emacs-lisp . t)
     (shell . t)
     (plantuml . t)
     (python . t)))
#+end_src

* Customize First Row and First Column cells

#+ATTR_ODT: :target "automatic_styles"
#+begin_src nxml
<style:style style:name="CustomTableFirstRowCell"
             style:family="table-cell">
  <style:table-cell-properties fo:background-color="#00ccff"
                               fo:border-bottom="0.002cm solid #000000"
                               fo:border-left="0.002cm solid #000000"
                               fo:border-right="0.002cm solid #000000"
                               fo:border-top="0.002cm solid #000000"
                               fo:padding="0.097cm" />
</style:style>
#+end_src

#+ATTR_ODT: :target "automatic_styles"
#+begin_src nxml
<style:style style:name="CustomTableFirstColumnCell"
             style:family="table-cell">
  <style:table-cell-properties fo:background-color="#F0C9C0"
                               fo:border-bottom="0.002cm solid #000000"
                               fo:border-left="0.002cm solid #000000"
                               fo:border-right="0.002cm solid #000000"
                               fo:border-top="0.002cm solid #000000"
                               fo:padding="0.097cm" />
</style:style>
#+end_src

* Apply ODT style to Python-generated Table

See

#+begin_src emacs-lisp :output results :results none
(info "(org) Results of Evaluation")
#+end_src

#+NAME: attr_wrap
#+BEGIN_SRC sh :var data="" :results output
# echo "#+ATTR_ODT: :page-break t :page-style \"Landscape\""
echo "#+ATTR_ODT: :style \"GriddedTable\""
echo "$data"
#+END_SRC

* Python block that generates a Table

#+name: prettytable
#+begin_src python :session one :exports results :results value raw :post attr_wrap(data=*this*)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from tabulate import tabulate

ax = plt.subplot(211)
rowLabels = ["state", u"↑", u"↓", u"←", u"→", "up", "down", "fire"]
rowColours = [
    "#EBB25E",
    "#F0C9C0",
    "#F0C9C0",
    "#F0C9C0",
    "#F0C9C0",
    "#F0C9C0",
    "#F0C9C0",
    "#F2F2F2",
]

colColors = ["#377eb8"]
colColors.extend(["#00ccff"] * 20)

data = [
    [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
]

column_labels = [
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "8",
    "9",
    "10",
    "11",
    "12",
    "13",
    "14",
    "15",
    "16",
    "17",
    "18",
    "19",
    "20",
    "21",
]

ax.axis("off")
ax.table(
    cellText=data,
    colLabels=column_labels,
    colColours=colColors,
    rowColours=rowColours,
    rowLabels=rowLabels,
    cellLoc="center",
    rowLoc="center",
    loc="center",
)

transpose_data = np.array(data)

data

df = pd.DataFrame(data, columns = column_labels)
df.index = rowLabels

df

tabulate(df,  headers=df.columns, tablefmt='orgtbl')
# filename = 'filename.png'
# plt.savefig(filename)
# filename
#+end_src


kjambunathan avatar Feb 23 '23 09:02 kjambunathan

You don't need list-tables ... A simple Org table with GriddedStyle that uses FirstRow and FirstColumn styles should suffice.

kjambunathan avatar Feb 23 '23 09:02 kjambunathan

One more comment ... the colors you see in the table doesn't come from the Python block. Only the table comes from the Python block, the colors are configured on the ODT side using nxml blocks.

kjambunathan avatar Feb 23 '23 09:02 kjambunathan

You can write any table as list table. When a table is in a list table form, you have access to individual table cells. This means you can pick and choose what style each table cell has.

Editing list tables is not convenient---the problem is you lose the 2-dimensional view of the contents---and assigning cell styles will be cumbersome.

Assigning cell styles individually to a list table is doable ... the time and effort of the developer---this is me---and one who would actually write the org file---that is you---should be well-justified.

If you give me a strong use case, I can invest some time.

kjambunathan avatar Feb 23 '23 13:02 kjambunathan

You'd better use libreoffice for very complex table and include the table into org file with:

#+ATTR_ODT: :transclude t
[[file:/tmp/a_complex_table.odt]]

The problem is that there is an extra empty line after the inserted table. Try export my comment with the attached file. a_complex_table.odt

QiangF avatar Feb 24 '23 03:02 QiangF

The transcluded file is put in a text:section, maybe we should add an option to not doing that:

#+ATTR_ODT: :transclude t :section nil
[[file:/tmp/a_complex_table.odt]]

QiangF avatar Feb 24 '23 03:02 QiangF