Tôi có thể định dạng các ô trong bảng chế độ tổ chức khác nhau tùy theo công thức không?


17

Tôi có một cột trong bảng chế độ org với các số trong mỗi ô. Tôi muốn thay đổi màu nền của ô thành màu đỏ nếu số dưới 1 hoặc trên 2.

Làm thế nào tôi có thể làm điều đó?


3
Câu hỏi tuyệt vời! Cả org-table-edit-formulasaka C-c 'org-table-toggle-coordinate-overlaysaka đều C-c }cung cấp manh mối về cách triển khai loại tính năng nổi bật này. Có lẽ một guru elisp sẽ cung cấp một số gợi ý hoặc ví dụ bổ sung.
Melioratus

Câu trả lời:


4

Tôi có định dạng toàn bảng để làm việc với một số Elisp:

Một công thức được đánh giá cho nội dung của các ô và được chuyển đổi thành màu bằng cách sử dụng độ dốc.

Tệp Org bao gồm mã:

#+name: item-prices
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| Item                  | Weight | Label Price | Ratio | CS-F | <-LR |   <-WR | CS-N | Si-N | Si-2 | St-N | St-F |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| Охотничье ружьё       |    3.3 |         400 |   121 |   40 |   10 |  11.82 |      |   40 |   40 |   50 |   60 |
| «Гадюка-5»            |   2.88 |        3000 |  1042 |  300 |   10 | 103.82 |      |  300 |  300 |  375 |  450 |
| Обрез                 |   1.90 |         200 |   105 |   20 |   10 |  10.00 |      |   20 |   20 |   25 |   30 |
| ПМм                   |   0.73 |         300 |   411 |   30 |   10 |  39.73 |      |   30 |   30 |   37 |   45 |
| АКМ-74/2 *            |   3.07 |        4000 |  1303 |  637 |   16 | 207.49 |      |  318 |  318 |  398 |  478 |
| АКМ-74/2У             |   2.71 |        2100 |   775 |  420 |   20 | 154.61 |      |  210 |  210 |  262 |  315 |
| ПБ-1с                 |   0.97 |         400 |   412 |  120 |   30 | 122.68 |  100 |   40 |   40 |   50 |   60 |
| «Чeйзер-13»           |   3.00 |        1250 |   417 |      |      |        |      |  125 |      |      |      |
| «Чeйзер-13» *         |        |        1250 |   417 |  200 |   16 |  66.33 |      |  100 |  100 |  125 |  149 |
| ХПСС-1м               |   0.94 |         600 |   682 |      |      |        |      |   60 |      |      |      |
| ХПСС-1м *             |   0.88 |         600 |   682 |   92 |   15 | 104.55 |      |   46 |   46 |   57 |   69 |
| «Фора-12»             |   0.83 |         600 |   723 |  120 |   20 | 143.37 |      |   60 |   60 |   74 |   90 |
| «Кора-919»            |   1.10 |        1500 |       |      |      |        |      |  150 |  150 |      |  225 |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| Прицел ПСО-1          |   0.20 |        1000 |  5000 |  100 |   10 | 500.00 |      |  150 |  150 |  150 |  200 |
| Детектор «Отклик»     |   0.00 |         500 |   inf |   50 |   10 |  50.00 |      |  100 |  100 |  175 |  250 |
| Детектор «Медведь»    |   0.00 |        1000 |   inf |  100 |   10 | 100.00 |      |      |      |      |  500 |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| Кожаная куртка        |   3.00 |         500 |   167 |  250 |   50 |  83.33 |      |    - |    - |  200 |      |
| Бронежилет ЧН-1       |   4.00 |        5000 |  1250 | 2500 |   50 | 625.00 |      |    - |    - |      |      |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| Аптечка               |   0.10 |         300 |  3000 |   30 |   10 | 300.00 |   16 |   45 |   45 |  105 |  150 |
| Бинт                  |   0.05 |         200 |  4000 |   20 |   10 | 400.00 |   11 |   30 |      |   70 |  100 |
| Противорад. п.        |   0.05 |         300 |  6000 |   30 |   10 | 600.00 |   16 |   45 |      |  105 |  150 |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| Водка «Казаки»        |   0.60 |         100 |   167 |  100 |  100 | 166.67 |  100 |    - |    - |    - |    - |
| «Завтрак туриста»     |   0.30 |         100 |   333 |  100 |  100 | 333.33 |      |    - |    - |    - |    - |
| Колбаса «Диетическая» |   0.50 |          50 |   100 |   50 |  100 | 100.00 |      |    - |    - |    - |    - |
| Хлеб                  |   0.30 |          20 |    67 |   20 |  100 |  66.67 |      |    - |    - |    - |    - |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| Патроны 9x18 мм       |   0.20 |          50 |   250 |    5 |   10 |  25.00 |    3 |    7 |    7 |    5 |    5 |
| Патроны 9x19 мм РВР   |   0.24 |         100 |   417 |   20 |   20 |  83.33 |   15 |      |      |      |      |
| Патроны 9x19 мм ЦМО   |   0.24 |         100 |   417 |      |    0 |   0.00 |      |   15 |   15 |   15 |   20 |
| Патроны 12x70 дробь   |   0.45 |          10 |    22 |    1 |   10 |   2.22 |    0 |    1 |      |    1 |    1 |
| Патроны 12x76 жекан   |   0.50 |          20 |    40 |    4 |   20 |   8.00 |    3 |    1 |      |    3 |    4 |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| Граната РГД-5         |   0.30 |         350 |       |      |      |        |      |   52 |   52 |   70 |   70 |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
| «Медуза»              |    0.5 |        4000 |  8000 |      |    0 |   0.00 |      | 2800 | 3600 | 2500 | 2800 |
|-----------------------+--------+-------------+-------+------+------+--------+------+------+------+------+------|
#+TBLFM: $4='(/ (string-to-number $3) (string-to-number $2));%1.f
#+TBLFM: $6='(/ (string-to-number $5) 0.01 (string-to-number $3));%1.f
#+TBLFM: $7=$5/$2;%1.2f

#+begin_src emacs-lisp :var table=item-prices
  (defun cs/itpl (low high r rlow rhigh)
    "Return the point between LOW and HIGH that corresponds to where R is between RLOW and RHIGH."
    (+ low (/ (* (- high low) (- r rlow)) (- rhigh rlow))))

  (defun cs/gradient (gradient p)
    (if (< p (caar gradient))
        (cdar gradient)
      (while (and (cdr gradient) (> p (caadr gradient)))
        (setq gradient (cdr gradient)))
      (if (null (cdr gradient))
          (cdar gradient)
        (list
         (cs/itpl (nth 1 (car gradient)) (nth 1 (cadr gradient)) p (caar gradient) (caadr gradient))
         (cs/itpl (nth 2 (car gradient)) (nth 2 (cadr gradient)) p (caar gradient) (caadr gradient))
         (cs/itpl (nth 3 (car gradient)) (nth 3 (cadr gradient)) p (caar gradient) (caadr gradient))))))

  (defun cs/scs-table-color ()
    (when (boundp 'cs/cell-color-overlays)
      (mapc #'delete-overlay cs/cell-color-overlays))
    (setq-local cs/cell-color-overlays nil)

    (save-excursion
      (org-table-map-tables
       (lambda ()
         (let* ((table (cl-remove-if-not #'listp (org-table-to-lisp))) ; remove 'hline
                (heading (car table))
                (element (org-element-at-point)))
           (while (and element (not (eq (car element) 'table)))
             (setq element (plist-get (cadr element) :parent)))
           (cond
            ((equal (plist-get (cadr element) :name) "item-prices")

             (org-table-analyze)
             (cl-loop for row being the elements of (cdr table) using (index row-index)
                      do (cl-loop for col being the elements of row using (index col-index)
                                  if (and
                                      (string-match "^..-.$" (nth col-index heading))
                                      (not (zerop (length col)))
                                      (not (equal "0" col)))
                                  do (progn
                                       (org-table-goto-field (format "@%d$%d" (+ 2 row-index) (1+ col-index)))
                                       (forward-char)
                                       (let* ((base-price (string-to-number (nth 2 row)))
                                              (vendor-price (string-to-number col))
                                              (ratio (/ vendor-price 1.0 base-price))
                                              (gradient '((0.10 #x40 #x00 #x00)
                                                          (0.20 #xC0 #x00 #x00)
                                                          (0.50 #x00 #x80 #x00)
                                                          (1.00 #x00 #xFF #x80)))
                                              (color (cs/gradient gradient ratio))
                                              (overlay (make-overlay
                                                        (progn (org-table-beginning-of-field 1) (backward-char) (point))
                                                        (progn (org-table-end-of-field 1) (forward-char) (point))))
                                              (bg (apply #'message "#%02x%02x%02x" color))
                                              (fg (if (< (apply #'+ color) 383) "#ffffff" "#000000"))
                                              (face (list
                                                     :background bg
                                                     :foreground fg)))
                                         (overlay-put overlay 'face face)
                                         (push overlay cs/cell-color-overlays)))))))))
       t)))

  (add-hook 'org-ctrl-c-ctrl-c-hook 'cs/scs-table-color nil t)
  nil
#+end_src

Điều đó thật tuyệt! Tôi rất thích đọc một mô tả sâu hơn một chút về cách tất cả được kết nối, ngay cả khi chỉ là "mã này chạy khi bạn thực hiện X, nó lấy Y và Z làm đầu vào và đây là những gì nó làm với bảng" :)
Trevoke

Cảm ơn. Đây là khá nhiều sự kết hợp của hai câu trả lời của bạn. Có một số dư thừa vì cả hai đều nhận được dữ liệu bảng từ org-babel và tìm kiếm khai báo tên bảng (để nó có thể thêm lớp phủ, v.v.). Từ đó, nó ánh xạ số hàng và số cột từ dữ liệu bảng đã nhận sang tọa độ ô bảng org. cs/itplthực hiện phép nội suy tuyến tính đơn giản và cs/gradientsử dụng phép đó để nội suy một màu bằng cách sử dụng danh sách các điểm dữ liệu và các điểm dừng màu. Từ đó, nó chỉ thêm một lớp phủ như trong câu trả lời của bạn. Ví dụ này là một chút không tầm thường vì nó liên quan đến dữ liệu từ nơi khác trong bảng.
Vladimir Panteleev

Đã cập nhật mã với phiên bản mới hơn để sửa lỗi dự phòng tên / dữ liệu, xóa lớp phủ cũ và đăng ký chính nó dưới dạng org-ctrl-c-ctrl-c-hook để bạn không phải đặt điểm trên khối mã để chạy nó Nó cũng có thể cập nhật tất cả các bảng trong tài liệu lịch sự của org-table-map-tables.
Vladimir Panteleev

Thật tuyệt. Tôi muốn thêm một số bình luận cho những người có thể đến đây và không quen thuộc với elisp, nhưng thật tuyệt vời, cảm ơn bạn!
Trevoke

4

Sử dụng lớp phủ là cách tôi sẽ muốn làm điều đó. Tôi có thể móc vào org-ctrl-c-ctrl-c-hook. Nó có nghĩa là tôi có thể nhấn Cc Cc để chạy kiểm tra.

Tôi cần kiểm tra chính xác rằng tôi đang ở trong một bảng và chạy cái này cho tất cả các ô.

Sau đó, tôi có lẽ cần phải nối vào chức năng căn chỉnh để làm lại các lớp phủ hoặc ít nhất là xóa chúng.

Mã này sẽ làm cho nền ô màu đỏ cho ô tôi đang ở nếu giá trị nhỏ hơn 1 hoặc lớn hơn 2 khi tôi nhấn Cc Cc ... Nhưng nó vẫn bị lỗi và sẽ xóa lớp phủ nếu một trong số chúng không ' t phù hợp với các quy tắc.

(defun staggering ()
  (save-excursion
    (let* ((ot-field-beginning (progn (org-table-beginning-of-field 1) (point)))
           (ot-field-end (progn (org-table-end-of-field 1) (point)))
           (cell-text (buffer-substring ot-field-beginning ot-field-end)))
      (if (or (< (string-to-number cell-text) 1)
              (> (string-to-number cell-text) 2))
          (overlay-put (make-overlay
                        (progn (org-table-beginning-of-field 1) (point))
                        (progn (org-table-end-of-field 1) (point)))
                       'face '(:background "#FF0000"))))))
(add-hook 'org-ctrl-c-ctrl-c-hook 'staggering)

2

Đây chưa phải là một câu trả lời nhưng tôi muốn theo dõi những điều tôi khám phá ở đây, vì họ có thể cho người khác một ý tưởng.

Có thể điều chỉnh một cáchđiều kiện giá trị của chính ô :

Chúng ta có thể tạo một hàm định dạng trong elisp và sau đó gọi nó từ dòng công thức:

#+BEGIN_SRC emacs-lisp :results silent
(defun danger (cell)
  (if (or (< (string-to-number cell) 1)
          (> (string-to-number cell) 2))
        (concat (int-to-string (string-to-number cell)) "!")
        cell))
#+END_SRC

Và nó có thể được sử dụng như vậy:

| String | Num | 
|--------+-----| 
| Foo    |   2 | 
| Bar    |   1 | 
| Baz    |  3! | 
|--------+-----|
#+TBLFM: $2='(danger @0$0)

Tôi nghĩ những gì tôi muốn có thể yêu cầu tạo ra một lớp phủ.


2

Emacs cung cấp hàm hi-lock-face-buffer M-s h rlàm nổi bật một biểu thức chính quy trong bộ đệm khi bạn nhập.

Tất cả những gì chúng ta cần là một biểu thức chính quy khớp với bất kỳ số nào không phải là 1 hoặc 2 và nằm trong ô của bảng. Thử đi:

| *\(-[0-9]+\|[03-9]\|[0-9][0-9]+\) *|

(Bạn có thể nhớ lại các biểu thức trước đó với M-nM-p.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.