# How to turn numeric percent cell content |86%| into progress bar ▊▊▊▊------ purely with TBLFM & elisp code?

This is a bit trickier, but the result is awesome:

|-------------------------------------------------------|
| Progress                                              |
| [%,                                                   |
| numeric percent                                       |
| cell content                                          |
| (Number from 0 to 100)]                               |
|-------------------------------------------------------|
| <numeric percent cell content (Number from 0 to 100)> |
|-------------------------------------------------------|
#+TBLFM: @1$1='(<calculation with numeric percent output, changing, could be 1 today, 17 tomorrow>)  For the sake of illustration, let's say right now calc outputs numeric percent 86: |-------------------------| | Progress | | [%, numeric percent | | cell content | | (Number from 0 to 100)] | |-------------------------| | 86 | |-------------------------| #+TBLFM: @1$1='(86)


The question now is: How to turn numeric percent cell content |86%| into progress bar ▊▊▊▊------ purely with TBLFM & elisp code?

I would go for replace-regexp-in-string

|-------------------------+------------------------------------------------------------------------------------------------------|
| Progress                |                                                                                                      |
|-------------------------+------------------------------------------------------------------------------------------------------|
| [%, numeric percent     | [%, graphical percent cell content, progress bar]                                                    |
| cell content            |                                                                                                      |
| (Number from 0 to 100)] |                                                                                                      |
|-------------------------+------------------------------------------------------------------------------------------------------|
| 86                      | ▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊-------------- |
|-------------------------+------------------------------------------------------------------------------------------------------|
#+TBLFM: @1$1='(86)::@1$2='(replace-regexp-in-string "<???>" "<???>" (number-to-string @1$1))  This here, ▊, is Left three quarters block, unicode U+258A If replace-regexp-in-string finds numeric percent cell content 86, it should place 86 times ▊. But, of course, 86 could be any number between 0 - 100. So, it's rather n. This here, -, is the common dash Additionally, if replace-regexp-in-string finds numeric percent cell content 86, it should append 14 times - to the 86 times ▊. But of course, it's rather 100 - n, than 14. It's not fixed, not always 14. And the question now is: How to make such a flexible replacement, additionally consisting not just of 1 new element, ▊, but 2, ▊ and -? If this is solved, we have it! Main question: So, the #TBLFM 1-liner, which does the trick, how does it look like? Follow-up question once main question is solved: How does everything look like with the length of the progress bar being flexible, connected to the org table cell width, whatever it is? Example |-------------------------+------------------------------------------------------------------------------------------------------| | Progress | | |-------------------------+------------------------------------------------------------------------------------------------------| | [%, numeric percent | [%, graphical percent cell content, progress bar] | | cell content | <100> | | (Number from 0 to 100)] | | |-------------------------+------------------------------------------------------------------------------------------------------| | 86 | ▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊-------------- | |-------------------------+------------------------------------------------------------------------------------------------------| #+TBLFM: @1$1='(86)::@1$2='(replace-regexp-in-string "<???>" "<???>" (number-to-string @1$1))

|-------------------------+------------|
| Progress                |            |
|-------------------------+------------|
| [%, numeric percent     | [%, graphical percent cell content, progress bar] |
| cell content            | <10>       |
| (Number from 0 to 100)] |            |
|-------------------------+------------|
| 86                      | ▊▊▊▊▊▊▊▊▊- |
|-------------------------+------------|
#+TBLFM: @1$1='(86)::@1$2='(replace-regexp-in-string "<???>" "<???>" (number-to-string @1$1))  One certainly has to work with, integrate <50> into the conversion somehow… and do rough rounding if necessary, like for example in case of 86 to 90… Update: If first consideration exceeds the possibilities of replace-regexp-in-string, if replace-regexp-in-string is not flexible enough for it, how can conversation of 'number n' into 'n times ▊ + 100-n times -' be acchieved more in general? Number n stored in cache, keyboard macros, emacs shell command, maybe the echo command, concat command, elisp, or a combination of some of those: There gotta has to be a way to turn a number between 0 and 100 into a visual representation in form of a progress bar. • emacs.stackexchange.com/tags/elisp/info – Drew Jun 24, 2023 at 1:42 • I would find 86 ▊ amd 14 - impossible to count. What's wrong with 86? Short and to the point and easy to interpret and understand. Graphical representations are undoubtedly useful (I would recommend Edward Tufte's books starting with "Visual Display of Quantitative Information" - but all of them are very good), but in this case all you get is visual clutter. Jun 24, 2023 at 2:31 • Have you tried orgtbl-ascii-plot? Jun 24, 2023 at 16:54 • @NickD: Justified input. Answer: 1st/2 reasons - higher motivation. Having progress displayed visually instead of numeric is more motivating, pushes you more to reach the end point. 2nd/2 reasons - more appealing. Humans a have stimulus expectation regarding design. This is met better by a progress bar than a simple numeric output. Jun 25, 2023 at 14:38 • @Juancho: Good point. Yes, I've turned to that - and away once I've noticed how complicated and over the top for my case it is. It even needs 2 additional installation for software parts. Those installations are on Microsoft owned github with lots of other platform issues from libre computing perspective, and need data transfer over the broken internet. I can't go that road. Jun 25, 2023 at 14:41 ## 3 Answers Specific basic solution: |----| | 86 | |----| #+TBLFM: @1$1='(concat (make-string (string-to-number @1$1) ?▊) (make-string (- 100 (string-to-number @1$1)) ?-))

1. Placing pointer in formula line
2. Typing C-c C-c

results into

|------------------------------------------------------------------------------------------------------|
| ▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊-------------- |
|------------------------------------------------------------------------------------------------------|
<pointer>#+TBLFM: @1$1='(concat (make-string (string-to-number @1$1) ?▊) (make-string (- 100 (string-to-number @1$1)) ?-))  Same formula, other numeric percent cell content |----| | 11 | |----| #+TBLFM: @1$1='(concat (make-string (string-to-number @1$1) ?▊) (make-string (- 100 (string-to-number @1$1)) ?-))


results into different status of progress bar

|------------------------------------------------------------------------------------------------------|
| ▊▊▊▊▊▊▊▊▊▊▊----------------------------------------------------------------------------------------- |
|------------------------------------------------------------------------------------------------------|
<pointer>#+TBLFM: @1$1='(concat (make-string (string-to-number @1$1) ?▊) (make-string (- 100 (string-to-number @1$1)) ?-))  TODO Extension by flexible table cell width value Useful sketch building block for this |--------------------------| | <24> | |--------------------------| | 24 | |--------------------------| #+TBLFM: @2$1='(replace-regexp-in-string "<\$$[0-9]*\$$>" "\\1" @1$1)  Fully-fledged specific solution - including flexibility in accordance with varying cell width: TL;DR - just give me the code: |---------------------------------------------| | <43> | |---------------------------------------------| | 86 | |---------------------------------------------| #+TBLFM: @2$1='(concat (make-string (round (* (string-to-number @2$1) (/ (string-to-number (replace-regexp-in-string "<\$$[0-9]*\$$>" "\\1" @1$1)) 100.0))) ?▊) (make-string (round (* (- 100 (string-to-number @2$1)) (/ (string-to-number (replace-regexp-in-string "<\$$[0-9]*\$$>" "\\1" @1$1)) 100.0))) ?-))


Notes:

• At least at 50% Block-fill won't fill uneven cell width completely - falling below or beyond will occur, for example at cell width 43 charactes, equal halfs will sum up to 42 or 44 characters, unavoidably. If staying in frame is of great importance for personal preference, changing rounding style from 'round' to 'floor' will do the trick - at the cost of lower accuracy on average.

• Successful approach for discovering the fully-fledged specific solution: Rapid prototyping in scratch buffer in org-mode - Making a table, developing a working formular in the most simple way, copying table including formular, inserting copy below with a bit of space, extending formular by next step on way to fully-fledged solution, in case breaks occur figuring out what causes them before doing the next extension. So, step by step to the final aim with many drafts in between, breaking down the big challenge into many building blocks building upon each other, and joining together working building blocks step by step. Common mistakes: Cell content is not exclusively a number, needs filtering of other characters like '<' and '>'; calculation doesn't work, because one of the multiple parts is not defined as a number, but a string - need for 'string-to-number' - zero-rounding loosing desired precision, because in calculation all parts are integers - for example 50/100, instead of 50/100.0 - making the calculation aiming at integer result - for example '0' - instead of floating point result - for example '0.5' - giving 'make-string' a floating point result for argument, how many times a certain string should be made, instead of giving it an integer result, which can be fixed by applying 'round' function right before passing result along to 'make-string'

– Drew
Jun 28, 2023 at 23:26
|  36 | ██▌          |
|  25 | █▊           |
|  16 | █▏           |
|   9 | ▋            |
|   4 | ▎            |
|   1 | ▏            |
|   0 |              |
|   1 | ▏            |
|   4 | ▎            |
|   9 | ▋            |
|  16 | █▏           |
|  25 | █▊           |
|  36 | ██▌          |
|  49 | ███▌         |
|  64 | ████▌        |
|  81 | █████▊       |
| 100 | ███████▏     |
| 121 | ████████▋    |
| 144 | ██████████▎  |
| 169 | ████████████ |
#+TBLFM: $2='(orgtbl-uc-draw-cont$1 0 169 12)
^ ^  ^   ^
| |  |   |
display column 1 ------------------/ |  |   |
|  |   |
values range from zero --------------/  |   |
to 169 ---------------------------------/   |
|
the column width is 12 ---------------------/


Org Mode comes with ASCII drawing of a column. Just type C-c " a with the cursor in the column.

Of course, this is not the answer to the question. But it could give inspiration. And it is purely TBLFM & elisp code.