1

Is there a way to merge columns together in an org-mode table? Often when I auto-create a table it will split certain fields into unnecessary columns. I would like a way to select those columns and then merge them together into one column.


Example

Input data:

Col1   Col2   Col3
a      b      longer data with spaces
a      b      another bit 

What I get:

|Col1|Col2|Col3   |    |    |      |
|a   |b   |longer |data|with|spaces|
|a   |b   |another|bit |    |      |

Now imagine the same problem but with many rows that have extra columns on the end. I want a way to select Col 3 and everything to the right and merge them together as one column.

Eg:

|Col1|Col2|Col3                   |
|a   |b   |longer data with spaces|
|a   |b   |another bit            |
6
  • Align the table and mark a rectangle that includes the `|' symbols between the columns that you want to merge. Then kill the rectangle. Org mode files are text, so even if there is not an org-table command to do what you want, you can often substitute a (set of) basic text changing command(s) to do what you want.
    – NickD
    Jan 14, 2021 at 14:08
  • That just deletes all of the data. I want a way to take several columns and merge them into one, combining the data they contain. Updated my question to make this more clear.
    – Cole
    Jan 14, 2021 at 22:51
  • No, it just deletes a column of '|' characters (and some '+' chars at the intersections with hlines). To do three columns, you first do two, realign the table (that allows you to mark and kill a rectangle that only contains what you want to get rid of) and then mark/kill another rectangle.
    – NickD
    Jan 14, 2021 at 23:25
  • Of course, if there were an org-table-merge command that did what you want, that's what you should use. But I don't think there is, so I suggested the above manual method as a way forward.
    – NickD
    Jan 14, 2021 at 23:30
  • Sorry @NickD I think I misread your comment. If I understand correctly you are suggesting deleting each set of | characters for the columns I want to merge using rectangular select. That works but is very tedious if you need to do 3+ columns, I was looking for a solution where I could just select a range of columns and use one set of commands to merge them.
    – Cole
    Jan 15, 2021 at 21:38

4 Answers 4

1

Could I suggest another approach: Prepare the text for easier conversion to a table. Look at the document string of org-table-convert-region to see what options and assumptions it has about field separator characters.

First, select the table text and run interactively the query-replace-regexp command with arguments +<tab>. That is "two or more spaces" to "a tab character". At the prompt, press ! to replace all.

Then, select the text again and run the command org-table-convert-region and you'll have your correctly formatted table in two easy steps.

1
  • 1
    ... or you can do C-u C-u C-u M-x org-table-convert-region and supply a regexp for the field separator <space><space>+.
    – NickD
    Jan 15, 2021 at 14:10
0

Here's a blow-by-blow account of the method I describe in the comments. We start with a table like this (it's better to have the spaces around each |, so I just realigned your table above with TAB to get that):

| Col1 | Col2 | Col3    |      |      |        |
| a    | b    | longer  | data | with | spaces |
| a    | b    | another | bit  |      |        |

Now place the cursor on the top | character after "Col3", place the mark there with C-<space>, move the cursor to the bottom row between the | and the b of "bit"., You have now marked a rectangle of width one character that includes the whole column of |. Now kill the rectangle with C-x r k. We end up with a table like this:

| Col1 | Col2 | Col3          |      |        |
| a    | b    | longer   data | with | spaces |
| a    | b    | another  bit  |      |        |

Now lather, rinse, repeat: Place the cursor on the | after "Col3", mark it with C-<space>, move the cursor to the space after the | in the same character column but on the bottom row of the table and kill that rectangle. You end up with this table:

| Col1 | Col2 | Col3                |        |
| a    | b    | longer   data  with | spaces |
| a    | b    | another  bit        |        |

Do the whole thing again with the remaining column of |. You end up with this table:

| Col1 | Col2 | Col3                        |
| a    | b    | longer   data  with  spaces |
| a    | b    | another  bit                |

You can, if you want, squash multiple spaces into a single space: select the table as a region in the usual way (place the cursor at the beginning of the table, set the mark with C-<space>, move the cursor to the end of the table) and then replace multiple spaces with a single space using a regexp: M-C-% <space><space>* RET <space> RET ! (where I've made the spaces explicit: when you type the command, just press the space bar every time you see ). The final ! says "replace all matches". That gives:

| Col1 | Col2 | Col3 |
| a | b | longer data with spaces |
| a | b | another bit |

Then realign the table with TAB and you are done:

| Col1 | Col2 | Col3                    |
| a    | b    | longer data with spaces |
| a    | b    | another bit             |

Once you have the keystrokes in your fingers, it goes fast. And although it's tedious for a table with many columns to be merged, it's not too bad. With only a little more effort, you can get a keyboard macro to do the rectangle killing, so all you have to do is move to the top | and execute the macro (the squashing of spaces and the final alignment are still done separately at the end). Further automation is possible but more complicated, so I'll stop here.

0

An other approach is to get what you want with auto-create and an argument.

Example

Input data:

Col1   Col2   Col3
a      b      longer data with spaces
a      b      another bit 

M-: Eval: (org-table-create-or-convert-from-region 2)

Just type (o-t-c-o-c and TAB 2)

Gives you what you want:

| Col1 | Col2 | Col3                    |
| a    | b    | longer data with spaces |
| a    | b    | another bit             |

When you specify a number, use that many spaces, or a TAB, as field separator

Shortcut: C-u 2 C-c |

0

You can delete all pipe char in a rectangle with this function :

(defun delete-pipe-char-in-rectangle (start end)
  "Delete all '|' in a rectangular region" 
  (interactive "r")
  (kill-rectangle start end)
  (with-temp-buffer
          (yank-rectangle)
          (goto-char (point-min))
          (while (search-forward "|" nil t) (replace-match ""))
          (kill-rectangle (point-min) (point-max)))
        (goto-char start)
        (yank-rectangle))

If you find it handy, you can bind it to a key of your choice. for instance for a global binding

(bind-key "C-c m" #'delete-pipe-char-in-rectangle)

Or only in org-mode

(bind-key "C-c m"  #'delete-pipe-char-in-rectangle org-mode-map)

(bind-key' is a macro that come whith the bind-key' package)

2
  • I am very new to emacs, and have often seen posts with custom functions but am not sure how to use them. I'm assuming I would put this in my .emacs file and then invoke with M-x? Do you know of any good resources for then binding it to a key (I'm guessing as part of the org layer)?
    – Cole
    Jan 15, 2021 at 23:24
  • To test evaluate this code with C-x C-e just after the last parenthesis. If that fit you, save it in your init file. You can bind it to any free key sequence, its up to your taste. (I suggest C-c m) I modify my answer to show an example.
    – gigiair
    Jan 16, 2021 at 8:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.