* RE: a ses question
[not found] <SJ1PR12MB6363EAEDEA36DA78E736B9DEA61EA@SJ1PR12MB6363.namprd12.prod.outlook.com>
@ 2023-10-29 16:43 ` Vincent Belaïche
2023-10-29 21:25 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-10-29 16:43 UTC (permalink / raw)
To: Andrés Ramírez; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1653 bytes --]
Please wite to me directly also, because I am not actively following the list.
I think that the issue is that you collect the result of the computation by reading the text in the print area. The print area is refreshed in a deferred way, and this is why it is not up-to-date when you read it with a buffer-substring call.
You need to call ses-write-cells before doing that. I have not tested it.
Vincent.
PS : you can set the cell value by just doing something like (setq A1 "value of A1" A2 "value of A2"), that will work for setting the input of the the computation, but the undoing won't work, and you will need an explicit ses-recalculate-… to trigger the computation. Also this is probably not futureproof because I intend to change the way how the ses cell value are stored. Maybe I should create a ses-setq form to do that. If you set the input as you are doing, I don't think that the ses-recalculate-… is needed, but if you collect the result from buffer-substringing the print-area you will need it.
________________________________
De : Andrés Ramírez <rrandresf@hotmail.com>
Envoyé : lundi 21 août 2023 12:38
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Objet : a ses question
Hi Vincent.
In case You are not following the emacs-help mailing list. I am sending You the link to the mail message.
–8<----------–—cut here----------–—start--------–—>8— https://lists.gnu.org/archive/cgi-bin/namazu.cgi?query=%2Bmessage-id%3ASJ1PR12MB6363267DB30BCE80E678BCFDA61EA%40SJ1PR12MB6363.namprd12.prod.outlook.com&submit=Search%21&idxname=help-gnu-emacs –8<----------–—cut here----------–—end----------–—>8—
Best Regards
[-- Attachment #2: Type: text/html, Size: 3858 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-10-29 16:43 ` a ses question Vincent Belaïche
@ 2023-10-29 21:25 ` Vincent Belaïche
2023-10-30 5:43 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-10-29 21:25 UTC (permalink / raw)
To: Andrés Ramírez; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2859 bytes --]
Just to complete my answer, if you do not want to rely on SES to do formatting output (with cell printers), then you can retrieve the computation result and format it explicitly with some code like this (not tested) :
(let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
*2 '>v ; use 'v> to read columnwsise
))))
(dolist (row (cdr range))
(dolist (cell (cdr row))
(insert (format "%f" cell) ; assuming all cells are floating point numbers
"&" ;; if & is the column separator
))
(insert "\\\\\n"; if \\ is the row separator
)))
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : dimanche 29 octobre 2023 17:43
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>
Objet : RE: a ses question
Please wite to me directly also, because I am not actively following the list.
I think that the issue is that you collect the result of the computation by reading the text in the print area. The print area is refreshed in a deferred way, and this is why it is not up-to-date when you read it with a buffer-substring call.
You need to call ses-write-cells before doing that. I have not tested it.
Vincent.
PS : you can set the cell value by just doing something like (setq A1 "value of A1" A2 "value of A2"), that will work for setting the input of the the computation, but the undoing won't work, and you will need an explicit ses-recalculate-… to trigger the computation. Also this is probably not futureproof because I intend to change the way how the ses cell value are stored. Maybe I should create a ses-setq form to do that. If you set the input as you are doing, I don't think that the ses-recalculate-… is needed, but if you collect the result from buffer-substringing the print-area you will need it.
________________________________
De : Andrés Ramírez <rrandresf@hotmail.com>
Envoyé : lundi 21 août 2023 12:38
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Objet : a ses question
Hi Vincent.
In case You are not following the emacs-help mailing list. I am sending You the link to the mail message.
–8<----------–—cut here----------–—start--------–—>8— https://lists.gnu.org/archive/cgi-bin/namazu.cgi?query=%2Bmessage-id%3ASJ1PR12MB6363267DB30BCE80E678BCFDA61EA%40SJ1PR12MB6363.namprd12.prod.outlook.com&submit=Search%21&idxname=help-gnu-emacs –8<----------–—cut here----------–—end----------–—>8—
Best Regards
[-- Attachment #2: Type: text/html, Size: 6058 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-10-29 21:25 ` Vincent Belaïche
@ 2023-10-30 5:43 ` Vincent Belaïche
2023-10-30 19:03 ` andrés ramírez
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-10-30 5:43 UTC (permalink / raw)
To: Andrés Ramírez; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 4172 bytes --]
Just reading again the code which I sent in my previous email, I found a problem, there would be one trailing column separator « & » too many. Probably the following would be better:
(let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
*2 '>v ; use 'v> to read columnwsise
))))
(dolist (row (cdr range)) ; cdr to remove 'vec
(pop row) ; remove 'vec
(while (progn
(insert (format "%f" (pop row))) ; assuming all cells are floating point numbers
(when row
(insert
"&" ; if & is the column separator
) t ; loop again
)))
(insert "\\\\\n"; if \\ is the row separator
)))
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : dimanche 29 octobre 2023 22:25
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>
Objet : RE: a ses question
Just to complete my answer, if you do not want to rely on SES to do formatting output (with cell printers), then you can retrieve the computation result and format it explicitly with some code like this (not tested) :
(let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
*2 '>v ; use 'v> to read columnwsise
))))
(dolist (row (cdr range))
(dolist (cell (cdr row))
(insert (format "%f" cell) ; assuming all cells are floating point numbers
"&" ;; if & is the column separator
))
(insert "\\\\\n"; if \\ is the row separator
)))
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : dimanche 29 octobre 2023 17:43
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>
Objet : RE: a ses question
Please wite to me directly also, because I am not actively following the list.
I think that the issue is that you collect the result of the computation by reading the text in the print area. The print area is refreshed in a deferred way, and this is why it is not up-to-date when you read it with a buffer-substring call.
You need to call ses-write-cells before doing that. I have not tested it.
Vincent.
PS : you can set the cell value by just doing something like (setq A1 "value of A1" A2 "value of A2"), that will work for setting the input of the the computation, but the undoing won't work, and you will need an explicit ses-recalculate-… to trigger the computation. Also this is probably not futureproof because I intend to change the way how the ses cell value are stored. Maybe I should create a ses-setq form to do that. If you set the input as you are doing, I don't think that the ses-recalculate-… is needed, but if you collect the result from buffer-substringing the print-area you will need it.
________________________________
De : Andrés Ramírez <rrandresf@hotmail.com>
Envoyé : lundi 21 août 2023 12:38
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Objet : a ses question
Hi Vincent.
In case You are not following the emacs-help mailing list. I am sending You the link to the mail message.
–8<----------–—cut here----------–—start--------–—>8— https://lists.gnu.org/archive/cgi-bin/namazu.cgi?query=%2Bmessage-id%3ASJ1PR12MB6363267DB30BCE80E678BCFDA61EA%40SJ1PR12MB6363.namprd12.prod.outlook.com&submit=Search%21&idxname=help-gnu-emacs –8<----------–—cut here----------–—end----------–—>8—
Best Regards
[-- Attachment #2: Type: text/html, Size: 8799 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: a ses question
2023-10-30 5:43 ` Vincent Belaïche
@ 2023-10-30 19:03 ` andrés ramírez
2023-11-01 19:08 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: andrés ramírez @ 2023-10-30 19:03 UTC (permalink / raw)
To: Vincent Belaïche; +Cc: emacs-devel, boruch_baum
Hi. Vincent.
I just yanked the elisp snippet You shared (without any modification) I
just did M-x eval-defun, and It gave me this error:
--8<---------------cut here---------------start------------->8---
Debugger entered--Lisp error: (error "Eager macro-expansion failure: (void-variable ses-...")
signal(error ("Eager macro-expansion failure: (void-variable ses-..."))
error("Eager macro-expansion failure: %S" (void-variable ses--cells))
internal-macroexpand-for-load((setq elisp--eval-defun-result (let ((print-level nil) (print-length nil)) (defalias 'smeter/further-processing #'(lambda nil "process input on as spreadsheet using ses formulae..." (interactive) (let (... ... ... ... ... ... myyyyymm mysesoutput chunk bigchunk) (goto-char ...) (setq beg ...) (setq workbook-filename ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq prevmeasu ...) (setq beg ...) (setq waterbill ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq measu ...) (setq beg ...) (setq myyyyymm ...) (if ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))))) t)
eval-region(162 5110 t #f(compiled-function (ignore) #<bytecode -0x5bb31d1b5fed60e>)) ; Reading at buffer position 2635
elisp--eval-defun()
eval-defun(nil)
funcall-interactively(eval-defun nil)
call-interactively(eval-defun record nil)
command-execute(eval-defun record)
execute-extended-command(nil "eval-defun" "eval-defun")
funcall-interactively(execute-extended-command nil "eval-defun" "eval-defun")
call-interactively(execute-extended-command nil nil)
command-execute(execute-extended-command)
--8<---------------cut here---------------end--------------->8---
Best Regards
Andrés Ramírez
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just reading again the code which I sent in my
Vincent> previous email, I found a problem, there would be one trailing column separator « & »
Vincent> too many. Probably the following would be better:
Vincent> (let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
Vincent> *2 '>v ; use 'v> to read columnwsise
Vincent> )))) (dolist (row (cdr range)) ; cdr to
Vincent> remove 'vec (pop row) ; remove 'vec (while (progn (insert (format "%f" (pop
Vincent> row))) ; assuming all cells are floating point numbers (when row (insert
Vincent> "&" ; if & is the column separator ) t ; loop again )))
Vincent> (insert "\\\\\n"; if \\ is the row separator )))
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: a ses question
@ 2023-11-01 17:07 Andrés Ramírez
0 siblings, 0 replies; 27+ messages in thread
From: Andrés Ramírez @ 2023-11-01 17:07 UTC (permalink / raw)
To: Vincent Belaïche; +Cc: emacs-devel, boruch_baum
[-- Attachment #1: Type: text/plain, Size: 3502 bytes --]
Hi again Vincent.
In the last email was missing the way the code looks now (I am updating
it cos now the ses computation result is recovered on a different way),
see the var mysesoutput.
--8<---------------cut here---------------start------------->8---
;;; with a buffer visiting the file /tmp/smeteroutput (output of smeterApp) run this function
(defun smeter/further-processing ()
"process input on as spreadsheet using ses formulae and extracting the ses computation result"
(interactive)
(let ( (sesbuf nil)
(measu nil)
(prevmeasu '())
(waterbill nil)
(beg nil)
(workbook-filename) myyyyymm mysesoutput)
(goto-char (point-min))
(setq beg (point)) (setq workbook-filename (buffer-substring-no-properties beg (line-end-position)))
(forward-line 1)
(setq beg (point)) (forward-line 4) (setq prevmeasu (split-string (buffer-substring-no-properties beg (point)) "\n"))
(setq beg (point)) (setq waterbill (buffer-substring-no-properties beg (line-end-position)))
(forward-line 1)
(setq beg (point)) (forward-line 4) (setq measu (buffer-substring-no-properties beg (point)))
(setq beg (point)) (setq myyyyymm (buffer-substring-no-properties beg (line-end-position)))
(if (not (file-readable-p workbook-filename))
(message (format "file not found: '%s'" workbook-filename))
(set-buffer (setq sesbuf (find-file-noselect workbook-filename)))
(ses-set-cell 12 2 'value (string-to-number waterbill)) ;;; C13
(ses-set-cell 2 1 'value (string-to-number (nth 0 prevmeasu))) ;;; B3
(ses-set-cell 3 1 'value (string-to-number (nth 1 prevmeasu)))
(ses-set-cell 4 1 'value (string-to-number (nth 2 prevmeasu)))
(ses-set-cell 5 1 'value (string-to-number (nth 3 prevmeasu))) ;;; B6
;;; NOTE2ME: yank is needed workaround-one (perhaps cos of deferred calculations) ¿How to call manually the deferred-calculation?
(ses-jump-safe "C3") ;;; paste 4 cells
(kill-new measu)
(yank) ;;; how to get rid of yank? 4 using ses-set-cell in place of yank
;;; (ses-recalculate-all)
;;; NOTE2ME: manual refreshing is needed cos ses-recalculate-all is not doing the job (then workaround-two)
;;; Key:R1 refreshOne cos of measures (all-refreshes-are-workaround-two)
;;; NOTE2ME: It should benefit a lot of persons knowing the right syntax 4 ses-range
(let ((minrow 2)(maxrow 5)(mincol 4)(maxcol 5)) (ses-recalculate-cell)) ;;; E3 F6
;;; Key:R2 refreshTwo cos of waterBill-change
(let ((minrow 2)(maxrow 5)(mincol 7)(maxcol 13)) (ses-recalculate-cell)) ;;; H3 N6
;;; below is for N3 N6 the computation result
(setq mysesoutput (concat (number-to-string (ses-cell-value 2 13)) "\n" (number-to-string (ses-cell-value 3 13)) "\n" (number-to-string (ses-cell-value 4 13)) "\n" (number-to-string (ses-cell-value 5 13))))
;;; kill ses buffer without confirmation (comment 2-lines below for not killing workbook-buffer)
(set-buffer-modified-p nil)
(let ((kill-buffer-query-functions nil)) (kill-buffer sesbuf))
;;;(smeter/compose-mail mysesoutput (- (length prevmeasu) 1) myyyyymm)
(with-temp-buffer (insert (replace-regexp-in-string "\n" "|" mysesoutput)) (write-file "/tmp/smeter-ses-computation-result-on-one-line"))
;;;(smeter/receipts-amounts)
)))
--8<---------------cut here---------------end--------------->8---
Best Regards
[-- Attachment #2: Type: message/rfc822, Size: 3170 bytes --]
From: andrés ramírez <rrandresf@hotmail.com>
To: Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc: emacs-devel <emacs-devel@gnu.org>, boruch_baum@gmx.com
Subject: Re: a ses question
Date: Mon, 30 Oct 2023 19:03:19 +0000
I just yanked the elisp snippet You shared (without any modification) I
just did M-x eval-defun, and It gave me this error:
--8<---------------cut here---------------start------------->8---
Debugger entered--Lisp error: (error "Eager macro-expansion failure: (void-variable ses-...")
signal(error ("Eager macro-expansion failure: (void-variable ses-..."))
error("Eager macro-expansion failure: %S" (void-variable ses--cells))
internal-macroexpand-for-load((setq elisp--eval-defun-result (let ((print-level nil) (print-length nil)) (defalias 'smeter/further-processing #'(lambda nil "process input on as spreadsheet using ses formulae..." (interactive) (let (... ... ... ... ... ... myyyyymm mysesoutput chunk bigchunk) (goto-char ...) (setq beg ...) (setq workbook-filename ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq prevmeasu ...) (setq beg ...) (setq waterbill ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq measu ...) (setq beg ...) (setq myyyyymm ...) (if ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))))) t)
eval-region(162 5110 t #f(compiled-function (ignore) #<bytecode -0x5bb31d1b5fed60e>)) ; Reading at buffer position 2635
elisp--eval-defun()
eval-defun(nil)
funcall-interactively(eval-defun nil)
call-interactively(eval-defun record nil)
command-execute(eval-defun record)
execute-extended-command(nil "eval-defun" "eval-defun")
funcall-interactively(execute-extended-command nil "eval-defun" "eval-defun")
call-interactively(execute-extended-command nil nil)
command-execute(execute-extended-command)
--8<---------------cut here---------------end--------------->8---
Best Regards
Andrés RamÃrez
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just reading again the code which I sent in my
Vincent> previous email, I found a problem, there would be one trailing column separator « & »
Vincent> too many. Probably the following would be better:
Vincent> (let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
Vincent> ââââââââââââââââââââââââââââââââââââââââââ *2 '>v ; use 'v> to read columnwsise
Vincent> ââââââââââââââââââââââââââââââââââââââââââ )))) (dolist (row (cdr range)) ; cdr to
Vincent> remove 'vec (pop row) ; remove 'vec (while (progn ââââââ (insert (format "%f" (pop
Vincent> row))) ; assuming all cells are floating point numbers ââââââ (when row ââââââ (insert
Vincent> ââââââ "&" ; if & is the column separator ââââââ ) t ; loop again ââââââââââââ )))
Vincent> (insert "\\\\\n"; if \\ is the row separator ââââââ )))
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-10-30 19:03 ` andrés ramírez
@ 2023-11-01 19:08 ` Vincent Belaïche
2023-11-01 19:23 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-01 19:08 UTC (permalink / raw)
To: Andrés Ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 3506 bytes --]
Hello,
Yes, I reproduced it, you can write the expression as follows :
(eval '(ses-range A1 C3 *2 >v))
to delay the macro expansion. I think that this kind of snippet used to work, I need to investigate why it does not work any longer.
V.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : lundi 30 octobre 2023 20:03
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: a ses question
Hi. Vincent.
I just yanked the elisp snippet You shared (without any modification) I
just did M-x eval-defun, and It gave me this error:
--8<---------------cut here---------------start------------->8---
Debugger entered--Lisp error: (error "Eager macro-expansion failure: (void-variable ses-...")
signal(error ("Eager macro-expansion failure: (void-variable ses-..."))
error("Eager macro-expansion failure: %S" (void-variable ses--cells))
internal-macroexpand-for-load((setq elisp--eval-defun-result (let ((print-level nil) (print-length nil)) (defalias 'smeter/further-processing #'(lambda nil "process input on as spreadsheet using ses formulae..." (interactive) (let (... ... ... ... ... ... myyyyymm mysesoutput chunk bigchunk) (goto-char ...) (setq beg ...) (setq workbook-filename ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq prevmeasu ...) (setq beg ...) (setq waterbill ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq measu ...) (setq beg ...) (setq myyyyymm ...) (if ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))))) t)
eval-region(162 5110 t #f(compiled-function (ignore) #<bytecode -0x5bb31d1b5fed60e>)) ; Reading at buffer position 2635
elisp--eval-defun()
eval-defun(nil)
funcall-interactively(eval-defun nil)
call-interactively(eval-defun record nil)
command-execute(eval-defun record)
execute-extended-command(nil "eval-defun" "eval-defun")
funcall-interactively(execute-extended-command nil "eval-defun" "eval-defun")
call-interactively(execute-extended-command nil nil)
command-execute(execute-extended-command)
--8<---------------cut here---------------end--------------->8---
Best Regards
Andrés Ramírez
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just reading again the code which I sent in my
Vincent> previous email, I found a problem, there would be one trailing column separator « & »
Vincent> too many. Probably the following would be better:
Vincent> (let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
Vincent> *2 '>v ; use 'v> to read columnwsise
Vincent> )))) (dolist (row (cdr range)) ; cdr to
Vincent> remove 'vec (pop row) ; remove 'vec (while (progn (insert (format "%f" (pop
Vincent> row))) ; assuming all cells are floating point numbers (when row (insert
Vincent> "&" ; if & is the column separator ) t ; loop again )))
Vincent> (insert "\\\\\n"; if \\ is the row separator )))
[-- Attachment #2: Type: text/html, Size: 8247 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-11-01 19:08 ` Vincent Belaïche
@ 2023-11-01 19:23 ` Vincent Belaïche
2023-11-02 11:20 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-01 19:23 UTC (permalink / raw)
To: Andrés Ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 4272 bytes --]
I see, I usually use this kind of snippet with some eval-region and the code where ses-range is found is in some buffer region, and in this case the macro expansion is delayed as Emacs does need to slurp the buffer region in the first place. I do this through some preprocessor of mine that allows to embed some Elisp code in comments in a file with another language.
This is why I was not aware the snippet would fail, anyway, I should have tested it before sending.
V.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : mercredi 1 novembre 2023 20:08
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
Hello,
Yes, I reproduced it, you can write the expression as follows :
(eval '(ses-range A1 C3 *2 >v))
to delay the macro expansion. I think that this kind of snippet used to work, I need to investigate why it does not work any longer.
V.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : lundi 30 octobre 2023 20:03
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: a ses question
Hi. Vincent.
I just yanked the elisp snippet You shared (without any modification) I
just did M-x eval-defun, and It gave me this error:
--8<---------------cut here---------------start------------->8---
Debugger entered--Lisp error: (error "Eager macro-expansion failure: (void-variable ses-...")
signal(error ("Eager macro-expansion failure: (void-variable ses-..."))
error("Eager macro-expansion failure: %S" (void-variable ses--cells))
internal-macroexpand-for-load((setq elisp--eval-defun-result (let ((print-level nil) (print-length nil)) (defalias 'smeter/further-processing #'(lambda nil "process input on as spreadsheet using ses formulae..." (interactive) (let (... ... ... ... ... ... myyyyymm mysesoutput chunk bigchunk) (goto-char ...) (setq beg ...) (setq workbook-filename ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq prevmeasu ...) (setq beg ...) (setq waterbill ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq measu ...) (setq beg ...) (setq myyyyymm ...) (if ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))))) t)
eval-region(162 5110 t #f(compiled-function (ignore) #<bytecode -0x5bb31d1b5fed60e>)) ; Reading at buffer position 2635
elisp--eval-defun()
eval-defun(nil)
funcall-interactively(eval-defun nil)
call-interactively(eval-defun record nil)
command-execute(eval-defun record)
execute-extended-command(nil "eval-defun" "eval-defun")
funcall-interactively(execute-extended-command nil "eval-defun" "eval-defun")
call-interactively(execute-extended-command nil nil)
command-execute(execute-extended-command)
--8<---------------cut here---------------end--------------->8---
Best Regards
Andrés Ramírez
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just reading again the code which I sent in my
Vincent> previous email, I found a problem, there would be one trailing column separator « & »
Vincent> too many. Probably the following would be better:
Vincent> (let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
Vincent> *2 '>v ; use 'v> to read columnwsise
Vincent> )))) (dolist (row (cdr range)) ; cdr to
Vincent> remove 'vec (pop row) ; remove 'vec (while (progn (insert (format "%f" (pop
Vincent> row))) ; assuming all cells are floating point numbers (when row (insert
Vincent> "&" ; if & is the column separator ) t ; loop again )))
Vincent> (insert "\\\\\n"; if \\ is the row separator )))
[-- Attachment #2: Type: text/html, Size: 9021 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-11-01 19:23 ` Vincent Belaïche
@ 2023-11-02 11:20 ` Vincent Belaïche
2023-11-02 11:27 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-02 11:20 UTC (permalink / raw)
To: Andrés Ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1.1: Type: text/plain, Size: 16798 bytes --]
I think that the problem is that some macros in SES are written in a dirty way as they use interned symbols.
I tried to fix it in the attached patch ses.diff, but there is still a problem. If I open an empty SES file toto.ses and evaluate this form:
(let ((the-ses-buffer (get-buffer "toto.ses")))
(with-current-buffer the-ses-buffer (insert (format "%S" (ses-range A1 A1)))))
then I get this backtrace:
Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
>(nil nil)
(or (> minrow maxrow) (> mincol maxcol))
(if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range"))
(let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r)))))
(let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc (and (symbolp (if (consp cur) (cdr cur) cur)) (get (if (consp cur) (cdr cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (cdr cur) cur) ses--named-cell-hashmap)) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r))))))
(let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc (and (symbolp (if (consp cur) (cdr cur) cur)) (get (if (consp cur) (cdr cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (cdr cur) cur) ses--named-cell-hashmap)) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r)))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe (prog1 nil (setq nil (cdr nil)))))) (cond ((eq x '>v) (let nil (setq transpose nil reorient-x nil reorient-y nil))) ((eq x '>^) (let nil (setq transpose nil reorient-x nil reorient-y t))) ((eq x '<^) (let nil (setq transpose nil reorient-x t reorient-y t))) ((eq x '<v) (let nil (setq transpose nil reorient-x t reorient-y nil))) ((eq x 'v>) (let nil (setq transpose t reorient-x nil reorient-y t))) ((eq x '^>) (let nil (setq transpose t reorient-x nil reorient-y nil))) ((eq x '^<) (let nil (setq transpose t reorient-x t reorient-y nil))) ((eq x 'v<) (let nil (setq transpose t reorient-x t reorient-y t))) ((memq x '(*1 *2 *)) (let nil (setq vectorize x))) ((eq x '!) (let nil (setq clean 'ses--clean-!))) ((eq x '_) (let nil (setq clean (list 'lambda '(&rest x) (list 'ses--clean-_ 'x (if nil (car-safe (prog1 nil (setq nil (cdr nil)))) 0)))))) (t (let nil (cond ((and (null (cdr (cdr result))) (memq x '(> <))) (setq nil (cons (intern (concat (symbol-name x) "v")) nil))) ((and (null (cdr (car result))) (memq x '(v ^))) (setq nil (cons (intern (concat (symbol-name x) ">")) nil))) (t (error "Unexpected flag `%S' in ses-range" x)))))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret (mapcar #'(lambda (x) (list x)) (car-safe (prog1 result (setq result (cdr result)))))) iter) (while result (setq iter ret) (let ((--dolist-tail-- (car-safe (prog1 result (setq result (cdr result))))) elt) (while --dolist-tail-- (setq elt (car --dolist-tail--)) (setcar iter (cons elt (car iter))) (setq iter (cdr iter)) (setq --dolist-tail-- (cdr --dolist-tail--))))) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda (clean result) (cons clean (cons ''vec (apply #'append result))))) (--cl-vectorize-*2-- #'(lambda (clean result) (cons clean (cons ''vec (mapcar #'(lambda (x) (cons clean (cons ''vec x))) result)))))) (progn (cond ((null vectorize) (let nil (cons clean (apply #'append result)))) ((eq vectorize '*1) (let nil (funcall --cl-vectorize-*1-- clean result))) ((eq vectorize '*2) (let nil (funcall --cl-vectorize-*2-- clean result))) ((eq vectorize '*) (let nil (funcall (if (cdr result) --cl-vectorize-*2-- --cl-vectorize-*1--) clean result)))))))
(format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc ...)) (if (eq rc :ses-named) (and ses--named-cell-hashmap ...) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let (...) (let ... ...)) (setq r (1+ r)))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe (prog1 nil ...)))) (cond ((eq x '>v) (let nil (setq transpose nil reorient-x nil reorient-y nil))) ((eq x '>^) (let nil (setq transpose nil reorient-x nil reorient-y t))) ((eq x '<^) (let nil (setq transpose nil reorient-x t reorient-y t))) ((eq x '<v) (let nil (setq transpose nil reorient-x t reorient-y nil))) ((eq x 'v>) (let nil (setq transpose t reorient-x nil reorient-y t))) ((eq x '^>) (let nil (setq transpose t reorient-x nil reorient-y nil))) ((eq x '^<) (let nil (setq transpose t reorient-x t reorient-y nil))) ((eq x 'v<) (let nil (setq transpose t reorient-x t reorient-y t))) ((memq x '...) (let nil (setq vectorize x))) ((eq x '!) (let nil (setq clean ...))) ((eq x '_) (let nil (setq clean ...))) (t (let nil (cond ... ... ...)))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret (mapcar ... ...)) iter) (while result (setq iter ret) (let (... elt) (while --dolist-tail-- ... ... ... ...))) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda (clean result) (cons clean ...))) (--cl-vectorize-*2-- #'(lambda (clean result) (cons clean ...)))) (progn (cond ((null vectorize) (let nil (cons clean ...))) ((eq vectorize '*1) (let nil (funcall --cl-vectorize-*1-- clean result))) ((eq vectorize '*2) (let nil (funcall --cl-vectorize-*2-- clean result))) ((eq vectorize '*) (let nil (funcall ... clean result))))))))
(insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let (...) (if ... ... rc))) (max (let (...) (if ... ... rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- ...) (r 0)) (while (< r --dotimes-limit--) (let ... ...) (setq r ...))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe ...))) (cond ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((memq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) (t (let nil ...))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret ...) iter) (while result (setq iter ret) (let ... ...)) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda ... ...)) (--cl-vectorize-*2-- #'(lambda ... ...))) (progn (cond ((null vectorize) (let nil ...)) ((eq vectorize ...) (let nil ...)) ((eq vectorize ...) (let nil ...)) ((eq vectorize ...) (let nil ...))))))))
(save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ... ...)) (max (let ... ...))) (message "min=%S max=%S" min max) (let ((minrow ...) (maxrow ...) (mincol ...) (maxcol ...)) (if (or ... ...) (error "Empty range")) (let (... ...) (while ... ... ...)))) (setq result (cons result-row result)) (while nil (let ((x ...)) (cond (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (t ...)))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let (... iter) (while result ... ...) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'...) (--cl-vectorize-*2-- #'...)) (progn (cond (... ...) (... ...) (... ...) (... ...))))))))
(let ((the-ses-buffer (get-buffer "toto.ses"))) (save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur ...) (min ...) (max ...)) (message "min=%S max=%S" min max) (let (... ... ... ...) (if ... ...) (let ... ...))) (setq result (cons result-row result)) (while nil (let (...) (cond ... ... ... ... ... ... ... ... ... ... ... ...))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr ...))) (if reorient-x nil (setq result (mapcar ... result))) (if transpose (progn (let ... ... ...))) (let* ((--cl-vectorize-*1-- ...) (--cl-vectorize-*2-- ...)) (progn (cond ... ... ... ...))))))))
eval((let ((the-ses-buffer (get-buffer "toto.ses"))) (save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean ...)) (let* (... ... ...) (message "min=%S max=%S" min max) (let ... ... ...)) (setq result (cons result-row result)) (while nil (let ... ...)) (if reorient-y (setcdr ... nil) (setq result ...)) (if reorient-x nil (setq result ...)) (if transpose (progn ...)) (let* (... ...) (progn ...))))))) nil)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
[cid:e4fc53b5-d7f1-4fb6-a7cc-9b980ba9b183]ses.diff<https://1drv.ms/u/s!AkDIBBjRAOVwg22q4IFutxJ-rfw8>
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : mercredi 1 novembre 2023 20:23
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
I see, I usually use this kind of snippet with some eval-region and the code where ses-range is found is in some buffer region, and in this case the macro expansion is delayed as Emacs does need to slurp the buffer region in the first place. I do this through some preprocessor of mine that allows to embed some Elisp code in comments in a file with another language.
This is why I was not aware the snippet would fail, anyway, I should have tested it before sending.
V.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : mercredi 1 novembre 2023 20:08
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
Hello,
Yes, I reproduced it, you can write the expression as follows :
(eval '(ses-range A1 C3 *2 >v))
to delay the macro expansion. I think that this kind of snippet used to work, I need to investigate why it does not work any longer.
V.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : lundi 30 octobre 2023 20:03
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: a ses question
Hi. Vincent.
I just yanked the elisp snippet You shared (without any modification) I
just did M-x eval-defun, and It gave me this error:
--8<---------------cut here---------------start------------->8---
Debugger entered--Lisp error: (error "Eager macro-expansion failure: (void-variable ses-...")
signal(error ("Eager macro-expansion failure: (void-variable ses-..."))
error("Eager macro-expansion failure: %S" (void-variable ses--cells))
internal-macroexpand-for-load((setq elisp--eval-defun-result (let ((print-level nil) (print-length nil)) (defalias 'smeter/further-processing #'(lambda nil "process input on as spreadsheet using ses formulae..." (interactive) (let (... ... ... ... ... ... myyyyymm mysesoutput chunk bigchunk) (goto-char ...) (setq beg ...) (setq workbook-filename ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq prevmeasu ...) (setq beg ...) (setq waterbill ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq measu ...) (setq beg ...) (setq myyyyymm ...) (if ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))))) t)
eval-region(162 5110 t #f(compiled-function (ignore) #<bytecode -0x5bb31d1b5fed60e>)) ; Reading at buffer position 2635
elisp--eval-defun()
eval-defun(nil)
funcall-interactively(eval-defun nil)
call-interactively(eval-defun record nil)
command-execute(eval-defun record)
execute-extended-command(nil "eval-defun" "eval-defun")
funcall-interactively(execute-extended-command nil "eval-defun" "eval-defun")
call-interactively(execute-extended-command nil nil)
command-execute(execute-extended-command)
--8<---------------cut here---------------end--------------->8---
Best Regards
Andrés Ramírez
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just reading again the code which I sent in my
Vincent> previous email, I found a problem, there would be one trailing column separator « & »
Vincent> too many. Probably the following would be better:
Vincent> (let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
Vincent> *2 '>v ; use 'v> to read columnwsise
Vincent> )))) (dolist (row (cdr range)) ; cdr to
Vincent> remove 'vec (pop row) ; remove 'vec (while (progn (insert (format "%f" (pop
Vincent> row))) ; assuming all cells are floating point numbers (when row (insert
Vincent> "&" ; if & is the column separator ) t ; loop again )))
Vincent> (insert "\\\\\n"; if \\ is the row separator )))
[-- Attachment #1.2: Type: text/html, Size: 25432 bytes --]
[-- Attachment #2: Outlook-ynkrmeif.png --]
[-- Type: image/png, Size: 159 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-11-02 11:20 ` Vincent Belaïche
@ 2023-11-02 11:27 ` Vincent Belaïche
2023-11-02 11:31 ` Vincent Belaïche
2023-11-02 18:19 ` Stefan Monnier
0 siblings, 2 replies; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-02 11:27 UTC (permalink / raw)
To: emacs-devel, monnier@iro.umontreal.ca
Cc: boruch_baum@gmx.com, Andrés Ramírez
[-- Attachment #1.1: Type: text/plain, Size: 17724 bytes --]
Dear Emacs experts,
Sorry for bothering, I am a bit at my end of wits. If I apply the patch attached to my previous email, load the patched ses.el and open an empty SES file toto.ses, and evaluate this expression in the *scratch* buffer,
(let ((the-ses-buffer (get-buffer "toto.ses")))
(with-current-buffer the-ses-buffer (insert (format "%S" (ses-range A1 A1)))))
then I get some error. It seems that the root cause is that the ses-sym-rowcol macro is evaluated (and not just expanded) in the *scratch* buffer instead of the toto.ses buffer, so symbol A1 has not 'ses-cell set to (0 . 0), and this makes it fail.
Vincent.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : jeudi 2 novembre 2023 12:20
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
I think that the problem is that some macros in SES are written in a dirty way as they use interned symbols.
I tried to fix it in the attached patch ses.diff, but there is still a problem. If I open an empty SES file toto.ses and evaluate this form:
(let ((the-ses-buffer (get-buffer "toto.ses")))
(with-current-buffer the-ses-buffer (insert (format "%S" (ses-range A1 A1)))))
then I get this backtrace:
Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
>(nil nil)
(or (> minrow maxrow) (> mincol maxcol))
(if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range"))
(let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r)))))
(let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc (and (symbolp (if (consp cur) (cdr cur) cur)) (get (if (consp cur) (cdr cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (cdr cur) cur) ses--named-cell-hashmap)) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r))))))
(let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc (and (symbolp (if (consp cur) (cdr cur) cur)) (get (if (consp cur) (cdr cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (cdr cur) cur) ses--named-cell-hashmap)) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r)))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe (prog1 nil (setq nil (cdr nil)))))) (cond ((eq x '>v) (let nil (setq transpose nil reorient-x nil reorient-y nil))) ((eq x '>^) (let nil (setq transpose nil reorient-x nil reorient-y t))) ((eq x '<^) (let nil (setq transpose nil reorient-x t reorient-y t))) ((eq x '<v) (let nil (setq transpose nil reorient-x t reorient-y nil))) ((eq x 'v>) (let nil (setq transpose t reorient-x nil reorient-y t))) ((eq x '^>) (let nil (setq transpose t reorient-x nil reorient-y nil))) ((eq x '^<) (let nil (setq transpose t reorient-x t reorient-y nil))) ((eq x 'v<) (let nil (setq transpose t reorient-x t reorient-y t))) ((memq x '(*1 *2 *)) (let nil (setq vectorize x))) ((eq x '!) (let nil (setq clean 'ses--clean-!))) ((eq x '_) (let nil (setq clean (list 'lambda '(&rest x) (list 'ses--clean-_ 'x (if nil (car-safe (prog1 nil (setq nil (cdr nil)))) 0)))))) (t (let nil (cond ((and (null (cdr (cdr result))) (memq x '(> <))) (setq nil (cons (intern (concat (symbol-name x) "v")) nil))) ((and (null (cdr (car result))) (memq x '(v ^))) (setq nil (cons (intern (concat (symbol-name x) ">")) nil))) (t (error "Unexpected flag `%S' in ses-range" x)))))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret (mapcar #'(lambda (x) (list x)) (car-safe (prog1 result (setq result (cdr result)))))) iter) (while result (setq iter ret) (let ((--dolist-tail-- (car-safe (prog1 result (setq result (cdr result))))) elt) (while --dolist-tail-- (setq elt (car --dolist-tail--)) (setcar iter (cons elt (car iter))) (setq iter (cdr iter)) (setq --dolist-tail-- (cdr --dolist-tail--))))) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda (clean result) (cons clean (cons ''vec (apply #'append result))))) (--cl-vectorize-*2-- #'(lambda (clean result) (cons clean (cons ''vec (mapcar #'(lambda (x) (cons clean (cons ''vec x))) result)))))) (progn (cond ((null vectorize) (let nil (cons clean (apply #'append result)))) ((eq vectorize '*1) (let nil (funcall --cl-vectorize-*1-- clean result))) ((eq vectorize '*2) (let nil (funcall --cl-vectorize-*2-- clean result))) ((eq vectorize '*) (let nil (funcall (if (cdr result) --cl-vectorize-*2-- --cl-vectorize-*1--) clean result)))))))
(format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc ...)) (if (eq rc :ses-named) (and ses--named-cell-hashmap ...) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let (...) (let ... ...)) (setq r (1+ r)))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe (prog1 nil ...)))) (cond ((eq x '>v) (let nil (setq transpose nil reorient-x nil reorient-y nil))) ((eq x '>^) (let nil (setq transpose nil reorient-x nil reorient-y t))) ((eq x '<^) (let nil (setq transpose nil reorient-x t reorient-y t))) ((eq x '<v) (let nil (setq transpose nil reorient-x t reorient-y nil))) ((eq x 'v>) (let nil (setq transpose t reorient-x nil reorient-y t))) ((eq x '^>) (let nil (setq transpose t reorient-x nil reorient-y nil))) ((eq x '^<) (let nil (setq transpose t reorient-x t reorient-y nil))) ((eq x 'v<) (let nil (setq transpose t reorient-x t reorient-y t))) ((memq x '...) (let nil (setq vectorize x))) ((eq x '!) (let nil (setq clean ...))) ((eq x '_) (let nil (setq clean ...))) (t (let nil (cond ... ... ...)))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret (mapcar ... ...)) iter) (while result (setq iter ret) (let (... elt) (while --dolist-tail-- ... ... ... ...))) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda (clean result) (cons clean ...))) (--cl-vectorize-*2-- #'(lambda (clean result) (cons clean ...)))) (progn (cond ((null vectorize) (let nil (cons clean ...))) ((eq vectorize '*1) (let nil (funcall --cl-vectorize-*1-- clean result))) ((eq vectorize '*2) (let nil (funcall --cl-vectorize-*2-- clean result))) ((eq vectorize '*) (let nil (funcall ... clean result))))))))
(insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let (...) (if ... ... rc))) (max (let (...) (if ... ... rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- ...) (r 0)) (while (< r --dotimes-limit--) (let ... ...) (setq r ...))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe ...))) (cond ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((memq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) (t (let nil ...))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret ...) iter) (while result (setq iter ret) (let ... ...)) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda ... ...)) (--cl-vectorize-*2-- #'(lambda ... ...))) (progn (cond ((null vectorize) (let nil ...)) ((eq vectorize ...) (let nil ...)) ((eq vectorize ...) (let nil ...)) ((eq vectorize ...) (let nil ...))))))))
(save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ... ...)) (max (let ... ...))) (message "min=%S max=%S" min max) (let ((minrow ...) (maxrow ...) (mincol ...) (maxcol ...)) (if (or ... ...) (error "Empty range")) (let (... ...) (while ... ... ...)))) (setq result (cons result-row result)) (while nil (let ((x ...)) (cond (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (t ...)))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let (... iter) (while result ... ...) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'...) (--cl-vectorize-*2-- #'...)) (progn (cond (... ...) (... ...) (... ...) (... ...))))))))
(let ((the-ses-buffer (get-buffer "toto.ses"))) (save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur ...) (min ...) (max ...)) (message "min=%S max=%S" min max) (let (... ... ... ...) (if ... ...) (let ... ...))) (setq result (cons result-row result)) (while nil (let (...) (cond ... ... ... ... ... ... ... ... ... ... ... ...))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr ...))) (if reorient-x nil (setq result (mapcar ... result))) (if transpose (progn (let ... ... ...))) (let* ((--cl-vectorize-*1-- ...) (--cl-vectorize-*2-- ...)) (progn (cond ... ... ... ...))))))))
eval((let ((the-ses-buffer (get-buffer "toto.ses"))) (save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean ...)) (let* (... ... ...) (message "min=%S max=%S" min max) (let ... ... ...)) (setq result (cons result-row result)) (while nil (let ... ...)) (if reorient-y (setcdr ... nil) (setq result ...)) (if reorient-x nil (setq result ...)) (if transpose (progn ...)) (let* (... ...) (progn ...))))))) nil)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
[cid:e4fc53b5-d7f1-4fb6-a7cc-9b980ba9b183]ses.diff<https://1drv.ms/u/s!AkDIBBjRAOVwg22q4IFutxJ-rfw8>
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : mercredi 1 novembre 2023 20:23
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
I see, I usually use this kind of snippet with some eval-region and the code where ses-range is found is in some buffer region, and in this case the macro expansion is delayed as Emacs does need to slurp the buffer region in the first place. I do this through some preprocessor of mine that allows to embed some Elisp code in comments in a file with another language.
This is why I was not aware the snippet would fail, anyway, I should have tested it before sending.
V.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : mercredi 1 novembre 2023 20:08
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
Hello,
Yes, I reproduced it, you can write the expression as follows :
(eval '(ses-range A1 C3 *2 >v))
to delay the macro expansion. I think that this kind of snippet used to work, I need to investigate why it does not work any longer.
V.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : lundi 30 octobre 2023 20:03
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: a ses question
Hi. Vincent.
I just yanked the elisp snippet You shared (without any modification) I
just did M-x eval-defun, and It gave me this error:
--8<---------------cut here---------------start------------->8---
Debugger entered--Lisp error: (error "Eager macro-expansion failure: (void-variable ses-...")
signal(error ("Eager macro-expansion failure: (void-variable ses-..."))
error("Eager macro-expansion failure: %S" (void-variable ses--cells))
internal-macroexpand-for-load((setq elisp--eval-defun-result (let ((print-level nil) (print-length nil)) (defalias 'smeter/further-processing #'(lambda nil "process input on as spreadsheet using ses formulae..." (interactive) (let (... ... ... ... ... ... myyyyymm mysesoutput chunk bigchunk) (goto-char ...) (setq beg ...) (setq workbook-filename ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq prevmeasu ...) (setq beg ...) (setq waterbill ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq measu ...) (setq beg ...) (setq myyyyymm ...) (if ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))))) t)
eval-region(162 5110 t #f(compiled-function (ignore) #<bytecode -0x5bb31d1b5fed60e>)) ; Reading at buffer position 2635
elisp--eval-defun()
eval-defun(nil)
funcall-interactively(eval-defun nil)
call-interactively(eval-defun record nil)
command-execute(eval-defun record)
execute-extended-command(nil "eval-defun" "eval-defun")
funcall-interactively(execute-extended-command nil "eval-defun" "eval-defun")
call-interactively(execute-extended-command nil nil)
command-execute(execute-extended-command)
--8<---------------cut here---------------end--------------->8---
Best Regards
Andrés Ramírez
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just reading again the code which I sent in my
Vincent> previous email, I found a problem, there would be one trailing column separator « & »
Vincent> too many. Probably the following would be better:
Vincent> (let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
Vincent> *2 '>v ; use 'v> to read columnwsise
Vincent> )))) (dolist (row (cdr range)) ; cdr to
Vincent> remove 'vec (pop row) ; remove 'vec (while (progn (insert (format "%f" (pop
Vincent> row))) ; assuming all cells are floating point numbers (when row (insert
Vincent> "&" ; if & is the column separator ) t ; loop again )))
Vincent> (insert "\\\\\n"; if \\ is the row separator )))
[-- Attachment #1.2: Type: text/html, Size: 28101 bytes --]
[-- Attachment #2: Outlook-ynkrmeif.png --]
[-- Type: image/png, Size: 159 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-11-02 11:27 ` Vincent Belaïche
@ 2023-11-02 11:31 ` Vincent Belaïche
2023-11-02 18:19 ` Stefan Monnier
1 sibling, 0 replies; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-02 11:31 UTC (permalink / raw)
To: emacs-devel; +Cc: boruch_baum@gmx.com, Andrés Ramírez
[-- Attachment #1.1: Type: text/plain, Size: 18322 bytes --]
I am on a fairly recent Emacs:
GNU Emacs 29.0.50 (build 3, x86_64-apple-darwin21.6.0, NS appkit-2113.60 Version 12.6.2 (Build 21G320)) of 2023-09-01
so I suspect that this problem is still on the HEAD master, but to be honest I have not tested it.
V.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : jeudi 2 novembre 2023 12:27
À : emacs-devel <emacs-devel@gnu.org>; monnier@iro.umontreal.ca <monnier@iro.umontreal.ca>
Cc : boruch_baum@gmx.com <boruch_baum@gmx.com>; Andrés Ramírez <rrandresf@hotmail.com>
Objet : RE: a ses question
Dear Emacs experts,
Sorry for bothering, I am a bit at my end of wits. If I apply the patch attached to my previous email, load the patched ses.el and open an empty SES file toto.ses, and evaluate this expression in the *scratch* buffer,
(let ((the-ses-buffer (get-buffer "toto.ses")))
(with-current-buffer the-ses-buffer (insert (format "%S" (ses-range A1 A1)))))
then I get some error. It seems that the root cause is that the ses-sym-rowcol macro is evaluated (and not just expanded) in the *scratch* buffer instead of the toto.ses buffer, so symbol A1 has not 'ses-cell set to (0 . 0), and this makes it fail.
Vincent.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : jeudi 2 novembre 2023 12:20
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
I think that the problem is that some macros in SES are written in a dirty way as they use interned symbols.
I tried to fix it in the attached patch ses.diff, but there is still a problem. If I open an empty SES file toto.ses and evaluate this form:
(let ((the-ses-buffer (get-buffer "toto.ses")))
(with-current-buffer the-ses-buffer (insert (format "%S" (ses-range A1 A1)))))
then I get this backtrace:
Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
>(nil nil)
(or (> minrow maxrow) (> mincol maxcol))
(if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range"))
(let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r)))))
(let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc (and (symbolp (if (consp cur) (cdr cur) cur)) (get (if (consp cur) (cdr cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (cdr cur) cur) ses--named-cell-hashmap)) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r))))))
(let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc (and (symbolp (if (consp cur) (cdr cur) cur)) (get (if (consp cur) (cdr cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (cdr cur) cur) ses--named-cell-hashmap)) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let ((row (+ r minrow))) (let ((--dotimes-limit-- (- maxcol mincol -1)) (c 0)) (while (< c --dotimes-limit--) (let ((col (+ c mincol))) (if (/= prev-row row) (progn (setq result (cons result-row result)) (setq result-row nil))) (setq result-row (cons (let ((cl-x (aref (aref ses--cells row) col))) (progn (progn (aref cl-x 0)))) result-row)) (setq prev-row row)) (setq c (1+ c))))) (setq r (1+ r)))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe (prog1 nil (setq nil (cdr nil)))))) (cond ((eq x '>v) (let nil (setq transpose nil reorient-x nil reorient-y nil))) ((eq x '>^) (let nil (setq transpose nil reorient-x nil reorient-y t))) ((eq x '<^) (let nil (setq transpose nil reorient-x t reorient-y t))) ((eq x '<v) (let nil (setq transpose nil reorient-x t reorient-y nil))) ((eq x 'v>) (let nil (setq transpose t reorient-x nil reorient-y t))) ((eq x '^>) (let nil (setq transpose t reorient-x nil reorient-y nil))) ((eq x '^<) (let nil (setq transpose t reorient-x t reorient-y nil))) ((eq x 'v<) (let nil (setq transpose t reorient-x t reorient-y t))) ((memq x '(*1 *2 *)) (let nil (setq vectorize x))) ((eq x '!) (let nil (setq clean 'ses--clean-!))) ((eq x '_) (let nil (setq clean (list 'lambda '(&rest x) (list 'ses--clean-_ 'x (if nil (car-safe (prog1 nil (setq nil (cdr nil)))) 0)))))) (t (let nil (cond ((and (null (cdr (cdr result))) (memq x '(> <))) (setq nil (cons (intern (concat (symbol-name x) "v")) nil))) ((and (null (cdr (car result))) (memq x '(v ^))) (setq nil (cons (intern (concat (symbol-name x) ">")) nil))) (t (error "Unexpected flag `%S' in ses-range" x)))))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret (mapcar #'(lambda (x) (list x)) (car-safe (prog1 result (setq result (cdr result)))))) iter) (while result (setq iter ret) (let ((--dolist-tail-- (car-safe (prog1 result (setq result (cdr result))))) elt) (while --dolist-tail-- (setq elt (car --dolist-tail--)) (setcar iter (cons elt (car iter))) (setq iter (cdr iter)) (setq --dolist-tail-- (cdr --dolist-tail--))))) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda (clean result) (cons clean (cons ''vec (apply #'append result))))) (--cl-vectorize-*2-- #'(lambda (clean result) (cons clean (cons ''vec (mapcar #'(lambda (x) (cons clean (cons ''vec x))) result)))))) (progn (cond ((null vectorize) (let nil (cons clean (apply #'append result)))) ((eq vectorize '*1) (let nil (funcall --cl-vectorize-*1-- clean result))) ((eq vectorize '*2) (let nil (funcall --cl-vectorize-*2-- clean result))) ((eq vectorize '*) (let nil (funcall (if (cdr result) --cl-vectorize-*2-- --cl-vectorize-*1--) clean result)))))))
(format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ((rc (and (symbolp (if (consp cur) (car cur) cur)) (get (if (consp cur) (car cur) cur) 'ses-cell)))) (if (eq rc :ses-named) (and ses--named-cell-hashmap (gethash (if (consp cur) (car cur) cur) ses--named-cell-hashmap)) rc))) (max (let ((rc ...)) (if (eq rc :ses-named) (and ses--named-cell-hashmap ...) rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- (- maxrow minrow -1)) (r 0)) (while (< r --dotimes-limit--) (let (...) (let ... ...)) (setq r (1+ r)))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe (prog1 nil ...)))) (cond ((eq x '>v) (let nil (setq transpose nil reorient-x nil reorient-y nil))) ((eq x '>^) (let nil (setq transpose nil reorient-x nil reorient-y t))) ((eq x '<^) (let nil (setq transpose nil reorient-x t reorient-y t))) ((eq x '<v) (let nil (setq transpose nil reorient-x t reorient-y nil))) ((eq x 'v>) (let nil (setq transpose t reorient-x nil reorient-y t))) ((eq x '^>) (let nil (setq transpose t reorient-x nil reorient-y nil))) ((eq x '^<) (let nil (setq transpose t reorient-x t reorient-y nil))) ((eq x 'v<) (let nil (setq transpose t reorient-x t reorient-y t))) ((memq x '...) (let nil (setq vectorize x))) ((eq x '!) (let nil (setq clean ...))) ((eq x '_) (let nil (setq clean ...))) (t (let nil (cond ... ... ...)))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret (mapcar ... ...)) iter) (while result (setq iter ret) (let (... elt) (while --dolist-tail-- ... ... ... ...))) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda (clean result) (cons clean ...))) (--cl-vectorize-*2-- #'(lambda (clean result) (cons clean ...)))) (progn (cond ((null vectorize) (let nil (cons clean ...))) ((eq vectorize '*1) (let nil (funcall --cl-vectorize-*1-- clean result))) ((eq vectorize '*2) (let nil (funcall --cl-vectorize-*2-- clean result))) ((eq vectorize '*) (let nil (funcall ... clean result))))))))
(insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let (...) (if ... ... rc))) (max (let (...) (if ... ... rc)))) (message "min=%S max=%S" min max) (let ((minrow (car min)) (maxrow (car max)) (mincol (cdr min)) (maxcol (cdr max))) (if (or (> minrow maxrow) (> mincol maxcol)) (error "Empty range")) (let ((--dotimes-limit-- ...) (r 0)) (while (< r --dotimes-limit--) (let ... ...) (setq r ...))))) (setq result (cons result-row result)) (while nil (let ((x (car-safe ...))) (cond ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((memq x ...) (let nil ...)) ((eq x ...) (let nil ...)) ((eq x ...) (let nil ...)) (t (let nil ...))))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let ((ret ...) iter) (while result (setq iter ret) (let ... ...)) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'(lambda ... ...)) (--cl-vectorize-*2-- #'(lambda ... ...))) (progn (cond ((null vectorize) (let nil ...)) ((eq vectorize ...) (let nil ...)) ((eq vectorize ...) (let nil ...)) ((eq vectorize ...) (let nil ...))))))))
(save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur (cons A1 A1)) (min (let ... ...)) (max (let ... ...))) (message "min=%S max=%S" min max) (let ((minrow ...) (maxrow ...) (mincol ...) (maxcol ...)) (if (or ... ...) (error "Empty range")) (let (... ...) (while ... ... ...)))) (setq result (cons result-row result)) (while nil (let ((x ...)) (cond (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (t ...)))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr (nreverse result)))) (if reorient-x nil (setq result (mapcar #'nreverse result))) (if transpose (progn (let (... iter) (while result ... ...) (setq result ret)))) (let* ((--cl-vectorize-*1-- #'...) (--cl-vectorize-*2-- #'...)) (progn (cond (... ...) (... ...) (... ...) (... ...))))))))
(let ((the-ses-buffer (get-buffer "toto.ses"))) (save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean 'list)) (let* ((cur ...) (min ...) (max ...)) (message "min=%S max=%S" min max) (let (... ... ... ...) (if ... ...) (let ... ...))) (setq result (cons result-row result)) (while nil (let (...) (cond ... ... ... ... ... ... ... ... ... ... ... ...))) (if reorient-y (setcdr (last result 2) nil) (setq result (cdr ...))) (if reorient-x nil (setq result (mapcar ... result))) (if transpose (progn (let ... ... ...))) (let* ((--cl-vectorize-*1-- ...) (--cl-vectorize-*2-- ...)) (progn (cond ... ... ... ...))))))))
eval((let ((the-ses-buffer (get-buffer "toto.ses"))) (save-current-buffer (set-buffer the-ses-buffer) (insert (format "%S" (let (result-row result (prev-row -1) reorient-x reorient-y transpose vectorize (clean ...)) (let* (... ... ...) (message "min=%S max=%S" min max) (let ... ... ...)) (setq result (cons result-row result)) (while nil (let ... ...)) (if reorient-y (setcdr ... nil) (setq result ...)) (if reorient-x nil (setq result ...)) (if transpose (progn ...)) (let* (... ...) (progn ...))))))) nil)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
[cid:e4fc53b5-d7f1-4fb6-a7cc-9b980ba9b183]ses.diff<https://1drv.ms/u/s!AkDIBBjRAOVwg22q4IFutxJ-rfw8>
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : mercredi 1 novembre 2023 20:23
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
I see, I usually use this kind of snippet with some eval-region and the code where ses-range is found is in some buffer region, and in this case the macro expansion is delayed as Emacs does need to slurp the buffer region in the first place. I do this through some preprocessor of mine that allows to embed some Elisp code in comments in a file with another language.
This is why I was not aware the snippet would fail, anyway, I should have tested it before sending.
V.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : mercredi 1 novembre 2023 20:08
À : Andrés Ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: a ses question
Hello,
Yes, I reproduced it, you can write the expression as follows :
(eval '(ses-range A1 C3 *2 >v))
to delay the macro expansion. I think that this kind of snippet used to work, I need to investigate why it does not work any longer.
V.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : lundi 30 octobre 2023 20:03
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: a ses question
Hi. Vincent.
I just yanked the elisp snippet You shared (without any modification) I
just did M-x eval-defun, and It gave me this error:
--8<---------------cut here---------------start------------->8---
Debugger entered--Lisp error: (error "Eager macro-expansion failure: (void-variable ses-...")
signal(error ("Eager macro-expansion failure: (void-variable ses-..."))
error("Eager macro-expansion failure: %S" (void-variable ses--cells))
internal-macroexpand-for-load((setq elisp--eval-defun-result (let ((print-level nil) (print-length nil)) (defalias 'smeter/further-processing #'(lambda nil "process input on as spreadsheet using ses formulae..." (interactive) (let (... ... ... ... ... ... myyyyymm mysesoutput chunk bigchunk) (goto-char ...) (setq beg ...) (setq workbook-filename ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq prevmeasu ...) (setq beg ...) (setq waterbill ...) (forward-line 1) (setq beg ...) (forward-line 4) (setq measu ...) (setq beg ...) (setq myyyyymm ...) (if ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))))) t)
eval-region(162 5110 t #f(compiled-function (ignore) #<bytecode -0x5bb31d1b5fed60e>)) ; Reading at buffer position 2635
elisp--eval-defun()
eval-defun(nil)
funcall-interactively(eval-defun nil)
call-interactively(eval-defun record nil)
command-execute(eval-defun record)
execute-extended-command(nil "eval-defun" "eval-defun")
funcall-interactively(execute-extended-command nil "eval-defun" "eval-defun")
call-interactively(execute-extended-command nil nil)
command-execute(execute-extended-command)
--8<---------------cut here---------------end--------------->8---
Best Regards
Andrés Ramírez
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just reading again the code which I sent in my
Vincent> previous email, I found a problem, there would be one trailing column separator « & »
Vincent> too many. Probably the following would be better:
Vincent> (let ((range (with-current-buffer the-ses-buffer (ses-range A1 C3 ; adapt to your case
Vincent> *2 '>v ; use 'v> to read columnwsise
Vincent> )))) (dolist (row (cdr range)) ; cdr to
Vincent> remove 'vec (pop row) ; remove 'vec (while (progn (insert (format "%f" (pop
Vincent> row))) ; assuming all cells are floating point numbers (when row (insert
Vincent> "&" ; if & is the column separator ) t ; loop again )))
Vincent> (insert "\\\\\n"; if \\ is the row separator )))
[-- Attachment #1.2: Type: text/html, Size: 30255 bytes --]
[-- Attachment #2: Outlook-ynkrmeif.png --]
[-- Type: image/png, Size: 159 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: a ses question
2023-11-02 11:27 ` Vincent Belaïche
2023-11-02 11:31 ` Vincent Belaïche
@ 2023-11-02 18:19 ` Stefan Monnier
2023-11-03 15:54 ` Vincent Belaïche
1 sibling, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2023-11-02 18:19 UTC (permalink / raw)
To: Vincent Belaïche
Cc: emacs-devel, boruch_baum@gmx.com, Andrés Ramírez
> (let ((the-ses-buffer (get-buffer "toto.ses")))
> (with-current-buffer the-ses-buffer (insert (format "%S" (ses-range A1 A1)))))
`ses-range` is a macro. The exact moment at which a macro is expanded
is not defined precisely. It can be expanded basically any time as long
as it's before the resulting code is needed for execution.
In other words, it's perfectly normal that the macro call `(ses-range A1 A1)`
is macro-expanded before any of the above code is executed.
If you don't want that, you need to use a function instead.
Stefan
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-11-02 18:19 ` Stefan Monnier
@ 2023-11-03 15:54 ` Vincent Belaïche
2023-11-03 22:13 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-03 15:54 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel, boruch_baum@gmx.com, Andrés Ramírez
[-- Attachment #1: Type: text/plain, Size: 1127 bytes --]
Dear Stefan,
Thank you for your reply. On second thought I think that I just did a mistake in the fix I intended to do. I am investigating it and will come back with a working fix for Andrès's problem or more questions …
V.
________________________________
De : Stefan Monnier <monnier@iro.umontreal.ca>
Envoyé : jeudi 2 novembre 2023 19:19
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>; Andrés Ramírez <rrandresf@hotmail.com>
Objet : Re: a ses question
> (let ((the-ses-buffer (get-buffer "toto.ses")))
> (with-current-buffer the-ses-buffer (insert (format "%S" (ses-range A1 A1)))))
`ses-range` is a macro. The exact moment at which a macro is expanded
is not defined precisely. It can be expanded basically any time as long
as it's before the resulting code is needed for execution.
In other words, it's perfectly normal that the macro call `(ses-range A1 A1)`
is macro-expanded before any of the above code is executed.
If you don't want that, you need to use a function instead.
Stefan
[-- Attachment #2: Type: text/html, Size: 2961 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: a ses question
2023-11-03 15:54 ` Vincent Belaïche
@ 2023-11-03 22:13 ` Vincent Belaïche
2023-11-04 13:46 ` andrés ramírez
[not found] ` <SJ1PR12MB636334BD471403C3F936BF25A6A4A@SJ1PR12MB6363.namprd12.prod.outlook.com>
0 siblings, 2 replies; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-03 22:13 UTC (permalink / raw)
To: Andrés Ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 2627 bytes --]
Dear Andrés,
Please find a tentative fix [https://res.cdn.office.net/assets/mail/file-icon/png/generic_16x16.png] ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg2_MBM_HJ7xOBFEl> that allows ses-range to be expanded not in a SES buffer, provided that the result is evaluated in a SES buffer. So you can get values from the SES buffer this way (without the (eval (quote …)) workaround to delay evaluation) :
(let ((range (with-current-buffer the-ses-buffer (ses-range A1 A2 >v))))
… do some processing with range. …
)
Doing this way rather than getting strings with buffer-substring from the print area you get raw values, not formatted values. This may be more convenient if you need to format them otherwise than SES does. Also you do not suffer from any text truncation done by SES due to cells' limited width. This is why this is the method which I always use, even though you need to do some reformatting of these values.
If you really want to read from the print area you need to call ses-write-cells before reading, to ensure that the print area is up-to-date.
Please tell be if the linked ses.el works fine for you, and then I would commit it.
V.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : vendredi 3 novembre 2023 16:54
À : Stefan Monnier <monnier@iro.umontreal.ca>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>; Andrés Ramírez <rrandresf@hotmail.com>
Objet : RE: a ses question
Dear Stefan,
Thank you for your reply. On second thought I think that I just did a mistake in the fix I intended to do. I am investigating it and will come back with a working fix for Andrès's problem or more questions …
V.
________________________________
De : Stefan Monnier <monnier@iro.umontreal.ca>
Envoyé : jeudi 2 novembre 2023 19:19
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>; Andrés Ramírez <rrandresf@hotmail.com>
Objet : Re: a ses question
> (let ((the-ses-buffer (get-buffer "toto.ses")))
> (with-current-buffer the-ses-buffer (insert (format "%S" (ses-range A1 A1)))))
`ses-range` is a macro. The exact moment at which a macro is expanded
is not defined precisely. It can be expanded basically any time as long
as it's before the resulting code is needed for execution.
In other words, it's perfectly normal that the macro call `(ses-range A1 A1)`
is macro-expanded before any of the above code is executed.
If you don't want that, you need to use a function instead.
Stefan
[-- Attachment #2: Type: text/html, Size: 7434 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: a ses question
2023-11-03 22:13 ` Vincent Belaïche
@ 2023-11-04 13:46 ` andrés ramírez
[not found] ` <SJ1PR12MB636334BD471403C3F936BF25A6A4A@SJ1PR12MB6363.namprd12.prod.outlook.com>
1 sibling, 0 replies; 27+ messages in thread
From: andrés ramírez @ 2023-11-04 13:46 UTC (permalink / raw)
To: Vincent Belaïche; +Cc: emacs-devel, boruch_baum@gmx.com
Hi. Vincent.
My comments below.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> [1 <text/plain; Windows-1252 (quoted-printable)>] Dear Andrés,
Vincent> Please find a tentative fix
Vincent> [https://res.cdn.office.net/assets/mail/file-icon/png/generic_16x16.png]
Vincent> ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg2_MBM_HJ7xOBFEl> that allows ses-range to be
Vincent> expanded not in a SES buffer, provided that the result is evaluated in a SES buffer. So
Vincent> you can get values from the SES buffer this way (without the (eval (quote …))
Vincent> workaround to delay evaluation) :
It works. Thanks
[...]
Vincent> Doing this way rather than getting strings with buffer-substring from the print area
Vincent> you get raw values, not formatted values. This may be more convenient if you need to
Vincent> format them otherwise than SES does. Also you do not suffer from any text truncation
Vincent> done by SES due to cells' limited width. This is why this is the method which I always
Vincent> use, even though you need to do some reformatting of these values.
It ended this way. Formatting was not needed. And also ses-write-cell
was needed.
--8<---------------cut here---------------start------------->8---
(ses-write-cells)
;;; '*1' formatting to vector also the range is the computation-result
(let ((range (ses-range N3 N6 *1)))
(pop range) ; remove 'vec
(setq mysesoutput (concat (number-to-string (nth 0 range)) "\n" (number-to-string (nth 1 range)) "\n" (number-to-string (nth 2 range)) "\n" (number-to-string (nth 3 range)))))
--8<---------------cut here---------------end--------------->8---
Vincent> If you really want to read from the print area you need to call ses-write-cells before
Vincent> reading, to ensure that the print area is up-to-date.
See above. ses-write-cells was also needed using that way.
Vincent> Please tell be if the linked ses.el works fine for you, and then I would commit it.
It works as it was intended to be used.
I have another question. But I am going to change the subject on another email.
Best Regards
Andrés Ramírez
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: using ses programatically (was: a ses question)
[not found] ` <SJ1PR12MB636334BD471403C3F936BF25A6A4A@SJ1PR12MB6363.namprd12.prod.outlook.com>
@ 2023-11-05 10:25 ` Vincent Belaïche
2023-11-05 14:58 ` andrés ramírez
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-05 10:25 UTC (permalink / raw)
To: andrés ramírez; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 3352 bytes --]
Dear Andrès,
I drafted a macro ses-setq to allow access a SES spreadsheet programatically, and I updated your code to use it. This allowed to remove all the workarounds. Please note that ses-setq is just a draft, far from complete. I intend to add some switches to allow access the cells eaither by cell name or by row col, and to modify either value or formula.
[https://res.cdn.office.net/assets/mail/file-icon/png/generic_16x16.png]andrès.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3AeKk2hwCznI9rK>
[https://res.cdn.office.net/assets/mail/file-icon/png/generic_16x16.png]ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3FksGYkC-uFDOQQ>
PS: I need to improve the macro, notable setting a cell value should also affect its formula if any.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : samedi 4 novembre 2023 14:55
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Objet : using ses programatically (was: a ses question)
Hi Vincent.
Thanks again for fixing the ses-range macro.
After applying that change, which btw fixed one of the workarounds in
the elisp code we have been improving on this thread.
The other workaround is the use of the yank function.
When I apply this patch to the code:
--8<---------------cut here---------------start------------->8---
diff -u /tmp/smeter.el /tmp/smeter_wished.el
--- /tmp/smeter.el 2023-11-04 13:24:42.030386021 +0000
+++ /tmp/smeter_wished.el 2023-11-04 13:26:25.128947532 +0000
@@ -15,7 +15,7 @@
(setq beg (point)) (forward-line 4) (setq prevmeasu (split-string (buffer-substring-no-properties beg (point)) "\n"))
(setq beg (point)) (setq waterbill (buffer-substring-no-properties beg (line-end-position)))
(forward-line 1)
- (setq beg (point)) (forward-line 4) (setq measu (buffer-substring-no-properties beg (point)))
+ (setq beg (point)) (forward-line 4) (setq measu (split-string (buffer-substring-no-properties beg (point)) "\n"))
(setq beg (point)) (setq myyyyymm (buffer-substring-no-properties beg (line-end-position)))
(if (not (file-readable-p workbook-filename))
(message (format "file not found: '%s'" workbook-filename))
@@ -25,11 +25,11 @@
(ses-set-cell 3 1 'value (string-to-number (nth 1 prevmeasu)))
(ses-set-cell 4 1 'value (string-to-number (nth 2 prevmeasu)))
(ses-set-cell 5 1 'value (string-to-number (nth 3 prevmeasu))) ;;; B6
- (ses-jump-safe "C3") ;;; paste 4 cells
- (kill-new measu)
- (yank)
+ (ses-set-cell 2 2 'value (string-to-number (nth 0 measu))) ;;; C3
+ (ses-set-cell 3 2 'value (string-to-number (nth 1 measu)))
+ (ses-set-cell 4 2 'value (string-to-number (nth 2 measu)))
+ (ses-set-cell 5 2 'value (string-to-number (nth 3 measu))) ;;; C6
(let ((range (ses-range E3 E6))) (ses-recalculate-cell))
-
(ses-write-cells)
;;; '*1' formatting to vector also the range is the computation-result
(let ((range (ses-range N3 N6 *1)))
Diff finished. Sat Nov 4 13:51:04 2023
--8<---------------cut here---------------end--------------->8---
The computation result is not the expected one (compared to the one that
uses yank). So it seems something
else is needed.
Any ideas why that patch does not do the right thing?
Best Regards
Andrés Ramírez
[-- Attachment #2: Type: text/html, Size: 6993 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: using ses programatically (was: a ses question)
2023-11-05 10:25 ` using ses programatically (was: a ses question) Vincent Belaïche
@ 2023-11-05 14:58 ` andrés ramírez
2023-11-05 16:55 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: andrés ramírez @ 2023-11-05 14:58 UTC (permalink / raw)
To: Vincent Belaïche; +Cc: emacs-devel, boruch_baum
Hi. Vincent.
My comments below.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Dear Andrès,
Vincent> I drafted a macro ses-setq to allow access a SES spreadsheet programatically, and I
Vincent> updated your code to use it. This allowed to remove all the workarounds. Please note
Vincent> that ses-setq is just a draft, far from complete. I intend to add some switches to
Vincent> allow access the cells eaither by cell name or by row col, and to modify either value
Vincent> or formula.
That's great. Just to mention again I have a newt-C-language app that
calls emacs this way:
--8<---------------cut here---------------start------------->8---
system ("cp workbook.ses /tmp; cp smeter.el /tmp; emacs -Q --batch -l /tmp/smeter.el /tmp/smeteroutput -f smeter/further-processing > /dev/null 2>&1");
--8<---------------cut here---------------end--------------->8---
And when the calling ends. It reads ses-output from /tmp/smeter.mail.
The C-language app does not known anything about emacs. So the logic of
calculation is within workbook.ses. That way when calculation logic
changes. The newt-C-language-App does not need to be changed. Just the
formulae within workbook.ses would be changed, which BTW is simpler than re-compiling the
newt-C-language-App.
[...]
The published version works as expected. Thanks for It.
But. I have a question. If emacs does NOT have the ses-setq
buffer (29.1 as an example). Which function calls should I do for having backward compatibility with older emacsen?.
I see ses-setq calls ses-write-cells. I added a call to ses-write-cells
after every call to ses-set-cell. But It did NOT work as expected.
Do You think It is possible to have that behaviour without using
ses-setq on older emacsen?
Vincent> PS: I need to improve the macro, notable setting a cell value should also affect its
Vincent> formula if any.
Ok.
BTW: JIC ses-setq is using 'cl-pushnew' this week there has been a long
discussion on emacs-devel about 'use or not to use those cl- prefixes
macros' an alternatives that are preloaded on emacs by default.
Best Regards
Andrés Ramírez
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: using ses programatically (was: a ses question)
2023-11-05 14:58 ` andrés ramírez
@ 2023-11-05 16:55 ` Vincent Belaïche
2023-11-05 19:33 ` andrés ramírez
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-05 16:55 UTC (permalink / raw)
To: andrés ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 3229 bytes --]
Dear Andrès,
Concerning the backward compatibility you could test emacs version in smeter.el to know whether the newer ses is distibuted. Otherwise, if not distributed you could have some newer ses.el copied to the same dir as smeter.el and change the load path in smeter.el for this newer ses.el to be loaded instead of the coming with the older emacs.
FYI, I have no idea when I will push to master the ses-setq etc... changes, and no idea when this is in a new release of Emacs.
Thank you for the information about the cl-... macros, I will I have look when time allows ...
Vincent.
PS : Maybe smeter.el would be simpler if the final sum was done by SES rather than org-table stuff.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : dimanche 5 novembre 2023 15:58
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: using ses programatically (was: a ses question)
Hi. Vincent.
My comments below.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Dear Andrès,
Vincent> I drafted a macro ses-setq to allow access a SES spreadsheet programatically, and I
Vincent> updated your code to use it. This allowed to remove all the workarounds. Please note
Vincent> that ses-setq is just a draft, far from complete. I intend to add some switches to
Vincent> allow access the cells eaither by cell name or by row col, and to modify either value
Vincent> or formula.
That's great. Just to mention again I have a newt-C-language app that
calls emacs this way:
--8<---------------cut here---------------start------------->8---
system ("cp workbook.ses /tmp; cp smeter.el /tmp; emacs -Q --batch -l /tmp/smeter.el /tmp/smeteroutput -f smeter/further-processing > /dev/null 2>&1");
--8<---------------cut here---------------end--------------->8---
And when the calling ends. It reads ses-output from /tmp/smeter.mail.
The C-language app does not known anything about emacs. So the logic of
calculation is within workbook.ses. That way when calculation logic
changes. The newt-C-language-App does not need to be changed. Just the
formulae within workbook.ses would be changed, which BTW is simpler than re-compiling the
newt-C-language-App.
[...]
The published version works as expected. Thanks for It.
But. I have a question. If emacs does NOT have the ses-setq
buffer (29.1 as an example). Which function calls should I do for having backward compatibility with older emacsen?.
I see ses-setq calls ses-write-cells. I added a call to ses-write-cells
after every call to ses-set-cell. But It did NOT work as expected.
Do You think It is possible to have that behaviour without using
ses-setq on older emacsen?
Vincent> PS: I need to improve the macro, notable setting a cell value should also affect its
Vincent> formula if any.
Ok.
BTW: JIC ses-setq is using 'cl-pushnew' this week there has been a long
discussion on emacs-devel about 'use or not to use those cl- prefixes
macros' an alternatives that are preloaded on emacs by default.
Best Regards
Andrés Ramírez
[-- Attachment #2: Type: text/html, Size: 5748 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: using ses programatically (was: a ses question)
2023-11-05 16:55 ` Vincent Belaïche
@ 2023-11-05 19:33 ` andrés ramírez
2023-11-18 22:55 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: andrés ramírez @ 2023-11-05 19:33 UTC (permalink / raw)
To: Vincent Belaïche; +Cc: emacs-devel, boruch_baum@gmx.com
Hi. Vincent.
My comments below.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Dear Andrès,
Vincent> Concerning the backward compatibility you could test emacs version in smeter.el to know
Vincent> whether the newer ses is distibuted. Otherwise, if not distributed you could have some
Vincent> newer ses.el copied to the same dir as smeter.el and change the load path in smeter.el
Vincent> for this newer ses.el to be loaded instead of the coming with the older emacs.
Ok.
Vincent> FYI, I have no idea when I will push to master the ses-setq etc... changes, and no idea
Vincent> when this is in a new release of Emacs.
Fine.
Vincent> Thank you for the information about the cl-... macros, I will I have look when time
Vincent> allows ...
Ok.
[...]
Vincent> PS : Maybe smeter.el would be simpler if the final sum was done by SES rather than
Vincent> org-table stuff.
Sure. I am thinking a little bit ahead. Why not testing setting formulae
on the fly for doing that final calculation? WDYT?.
Thank for your help.
Andrés Ramírez
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: using ses programatically (was: a ses question)
2023-11-05 19:33 ` andrés ramírez
@ 2023-11-18 22:55 ` Vincent Belaïche
2023-11-19 19:24 ` andrés ramírez
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-18 22:55 UTC (permalink / raw)
To: andrés ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 2567 bytes --]
Dear Andrès,
I attached an updated ses-setq macro.
[https://res.cdn.office.net/assets/mail/file-icon/png/generic_16x16.png]ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3PG8zN19RiycfN_>
You can both set values and formulas programmatically. There are 4 switches sv rcv sf and rcf. The …v sitches are for setting values, and the …f switches are for setting formula. The s… switches are for indicating the cell by symbol (e.g. A1) and the rc… switches are for indicating the cell by row col coordinate, (e.g. 0 0 are for A1). Default initial switch is sv. You can change the current switch with the :: argument.
So
(ses-setq A1 1 :: sf B1 (1+ A1))
will set A1 to 1, and B1 to the formula that adds 1 to A1, so B1 will be 2.
Other examples that do the same job :
(ses-setq :: rcv 0 0 1 :: sf B1 (1+ A1))
Or
(ses-setq A1 1 :: rcf 0 1 (1+ A1))
I still need more work to handle properly the safe function stuff in the case of setting formulae.
In the case of smeter you could use the sf / rcf switch to set any formula you like in order to compute the result.
Vincent.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : dimanche 5 novembre 2023 20:33
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: using ses programatically (was: a ses question)
Hi. Vincent.
My comments below.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Dear Andrès,
Vincent> Concerning the backward compatibility you could test emacs version in smeter.el to know
Vincent> whether the newer ses is distibuted. Otherwise, if not distributed you could have some
Vincent> newer ses.el copied to the same dir as smeter.el and change the load path in smeter.el
Vincent> for this newer ses.el to be loaded instead of the coming with the older emacs.
Ok.
Vincent> FYI, I have no idea when I will push to master the ses-setq etc... changes, and no idea
Vincent> when this is in a new release of Emacs.
Fine.
Vincent> Thank you for the information about the cl-... macros, I will I have look when time
Vincent> allows ...
Ok.
[...]
Vincent> PS : Maybe smeter.el would be simpler if the final sum was done by SES rather than
Vincent> org-table stuff.
Sure. I am thinking a little bit ahead. Why not testing setting formulae
on the fly for doing that final calculation? WDYT?.
Thank for your help.
Andrés Ramírez
[-- Attachment #2: Type: text/html, Size: 7238 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: using ses programatically (was: a ses question)
2023-11-18 22:55 ` Vincent Belaïche
@ 2023-11-19 19:24 ` andrés ramírez
2023-11-19 23:18 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: andrés ramírez @ 2023-11-19 19:24 UTC (permalink / raw)
To: Vincent Belaïche; +Cc: emacs-devel, boruch_baum@gmx.com
Hi. Vincent.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> I attached an updated ses-setq macro.
[...]
I have just tested the last version of ses.el
And I have found a trivial difference.
When I code:
--8<---------------cut here---------------start------------->8---
(ses-setq :: sf N7 (+ N3 N4 N5 N6))
(setq mysum (number-to-string (ses-cell-value 6 13)))
(message (format "the sum: '%s'" mysum))
--8<---------------cut here---------------end--------------->8---
the output is:
,---- [ single digit output ]
| the sum: ’192.6’
`----
But then when code is:
--8<---------------cut here---------------start------------->8---
(ses-setq :: sf N7 (apply 'ses+ (ses-range N3 N6)))
(setq mysum (number-to-string (ses-cell-value 6 13)))
(message (format "the sum: '%s'" mysum))
--8<---------------cut here---------------end--------------->8---
the output is:
,---- [ more than one digit decimal output ]
| the sum: ’192.60000000000002’
`----
Any idea why the difference?
BTW: yesterday I have found a different issue when using keyboard
macros for copying some specific cells to different lines on another
buffer. But. Let's end this part for asking about that one.
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: using ses programatically (was: a ses question)
2023-11-19 19:24 ` andrés ramírez
@ 2023-11-19 23:18 ` Vincent Belaïche
2023-11-19 23:24 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-19 23:18 UTC (permalink / raw)
To: andrés ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 2525 bytes --]
Hello,
Maybe it is due to the order of summing, ses+ is defined as follows:
(defun ses+ (&rest args)
"Compute the sum of the arguments, ignoring blanks."
(apply #'+ (apply #'ses-delete-blanks args)))
But ses-delete-blanks will revert the order, so in the second case you sum N6 N5 N4 N3 and not N3 N4 N5 N6.
Have you tried to use in both case '+ or 'ses+, but not '+ in one case and 'ses+ in the other case.
BR,
V.
PS : Basically you are summing IEEE 754 floating point numbers, so there are some minor rounding errors when converting form decimal to binary and vice versa, because IEEE 754 is using a 2 exponent.
If you are doing some accounting maybe it is better to use Calc fixed point numbers, so you would have interger summing and no rounding errors as Calc is using a 10 exponent.
Of course using Calc is less practical, this is one of my big todo to make SES/Calc interaction easier.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : dimanche 19 novembre 2023 20:24
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: using ses programatically (was: a ses question)
Hi. Vincent.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> I attached an updated ses-setq macro.
[...]
I have just tested the last version of ses.el
And I have found a trivial difference.
When I code:
--8<---------------cut here---------------start------------->8---
(ses-setq :: sf N7 (+ N3 N4 N5 N6))
(setq mysum (number-to-string (ses-cell-value 6 13)))
(message (format "the sum: '%s'" mysum))
--8<---------------cut here---------------end--------------->8---
the output is:
,---- [ single digit output ]
| the sum: ’192.6’
`----
But then when code is:
--8<---------------cut here---------------start------------->8---
(ses-setq :: sf N7 (apply 'ses+ (ses-range N3 N6)))
(setq mysum (number-to-string (ses-cell-value 6 13)))
(message (format "the sum: '%s'" mysum))
--8<---------------cut here---------------end--------------->8---
the output is:
,---- [ more than one digit decimal output ]
| the sum: ’192.60000000000002’
`----
Any idea why the difference?
BTW: yesterday I have found a different issue when using keyboard
macros for copying some specific cells to different lines on another
buffer. But. Let's end this part for asking about that one.
[-- Attachment #2: Type: text/html, Size: 7244 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: using ses programatically (was: a ses question)
2023-11-19 23:18 ` Vincent Belaïche
@ 2023-11-19 23:24 ` Vincent Belaïche
2023-11-20 0:33 ` andrés ramírez
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-11-19 23:24 UTC (permalink / raw)
To: andrés ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 3354 bytes --]
Just to make my point more clear, with Calc you need to write '(float 12 -1) for 1.2, and use calcFunc-add instead of +, ie (apply 'calcFunc-add (ses-range N3 N6)). Also the cell printer should be math-format-value.
Note that with IEEE754 numbers ses+ is not so useful if you are using ses-range as you can delete blank by adding a ! argument, ie (apply 'ses+ (ses-range N3 N6)) is almost the same as (apply '+ (ses-range N3 N6 !)), the sole difference is that the former does the summing in revert order.
V.
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : lundi 20 novembre 2023 00:18
À : andrés ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: using ses programatically (was: a ses question)
Hello,
Maybe it is due to the order of summing, ses+ is defined as follows:
(defun ses+ (&rest args)
"Compute the sum of the arguments, ignoring blanks."
(apply #'+ (apply #'ses-delete-blanks args)))
But ses-delete-blanks will revert the order, so in the second case you sum N6 N5 N4 N3 and not N3 N4 N5 N6.
Have you tried to use in both case '+ or 'ses+, but not '+ in one case and 'ses+ in the other case.
BR,
V.
PS : Basically you are summing IEEE 754 floating point numbers, so there are some minor rounding errors when converting form decimal to binary and vice versa, because IEEE 754 is using a 2 exponent.
If you are doing some accounting maybe it is better to use Calc fixed point numbers, so you would have interger summing and no rounding errors as Calc is using a 10 exponent.
Of course using Calc is less practical, this is one of my big todo to make SES/Calc interaction easier.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : dimanche 19 novembre 2023 20:24
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: using ses programatically (was: a ses question)
Hi. Vincent.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> I attached an updated ses-setq macro.
[...]
I have just tested the last version of ses.el
And I have found a trivial difference.
When I code:
--8<---------------cut here---------------start------------->8---
(ses-setq :: sf N7 (+ N3 N4 N5 N6))
(setq mysum (number-to-string (ses-cell-value 6 13)))
(message (format "the sum: '%s'" mysum))
--8<---------------cut here---------------end--------------->8---
the output is:
,---- [ single digit output ]
| the sum: ’192.6’
`----
But then when code is:
--8<---------------cut here---------------start------------->8---
(ses-setq :: sf N7 (apply 'ses+ (ses-range N3 N6)))
(setq mysum (number-to-string (ses-cell-value 6 13)))
(message (format "the sum: '%s'" mysum))
--8<---------------cut here---------------end--------------->8---
the output is:
,---- [ more than one digit decimal output ]
| the sum: ’192.60000000000002’
`----
Any idea why the difference?
BTW: yesterday I have found a different issue when using keyboard
macros for copying some specific cells to different lines on another
buffer. But. Let's end this part for asking about that one.
[-- Attachment #2: Type: text/html, Size: 8433 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: using ses programatically (was: a ses question)
2023-11-19 23:24 ` Vincent Belaïche
@ 2023-11-20 0:33 ` andrés ramírez
2023-12-24 11:51 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: andrés ramírez @ 2023-11-20 0:33 UTC (permalink / raw)
To: Vincent Belaïche; +Cc: emacs-devel, boruch_baum@gmx.com
Hi. Vincent.
I am going to reply both of your emails from this one.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just to make my point more clear,
Vincent> with Calc you need to write '(float 12 -1) for 1.2, and use calcFunc-add instead of +,
Vincent> ie (apply 'calcFunc-add (ses-range N3 N6)). Also the cell printer should be
Vincent> math-format-value.
It sounds interesting to try.
Vincent> Note that with IEEE754 numbers ses+ is not so useful if you are using ses-range as you
Vincent> can delete blank by adding a ! argument, ie (apply 'ses+ (ses-range N3 N6)) is almost
Vincent> the same as (apply '+ (ses-range N3 N6 !)), the sole difference is that the former does
Vincent> the summing in revert order.
Well explained Vincent. Thanks for the explanation. I do not use ses
daily. So I discover ses (three years ago). And at that time
workbook.ses was created. From that time to now workbook.ses has been my
only contact with ses (with the exception of yesterday). Just changing
values, not formulae, formulaes has been almost the same from three
years ago. But Now that You have mentioned it. Three years ago I though
why using '+ when 'ses+ always take care of blanks. So that's the one to
use when using ses. Just until now You have showed me there is a
difference. So now the question could be "why using 'ses+ when '+ is
enough even for eliminating the blank values?"
It ended like this:
--8<---------------cut here---------------start------------->8---
(ses-setq :: sf N7 (apply '+ (ses-range N3 N6 !)))
--8<---------------cut here---------------end--------------->8---
Vincent> emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com> Objet :
Vincent> RE: using ses programatically (was: a ses question)
[...]
Vincent> Have you tried to use in both case '+ or 'ses+, but not '+ in one case and 'ses+ in the
Vincent> other case.
Well. Actually I started with the simple case just using '+ and after it
I replaced with the real formulae(which contained 'ses+) as the other ones within
workbook.ses. I am happy I had try it that way. So I have learn the
difference between 'ses+ and '+. It was a happy coincidence.
BTW.
s/"Compute the sum of the arguments, ignoring blanks."/"Compute the sum of the arguments in reverse order, ignoring blanks."
Could above be ok (for improving the documentation of 'ses+)?
Best Regards
Andrés Ramírez
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: using ses programatically (was: a ses question)
2023-11-20 0:33 ` andrés ramírez
@ 2023-12-24 11:51 ` Vincent Belaïche
2023-12-24 15:44 ` andrés ramírez
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-12-24 11:51 UTC (permalink / raw)
To: andrés ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1.1: Type: text/plain, Size: 3671 bytes --]
Hello Andrès,
That is a good point that ses+ needs better documentation : I attached an update of ses.texi, [cid:55adc5ac-b103-461e-8604-536c90cae07a] ses.texi.diff<https://1drv.ms/u/s!AkDIBBjRAOVwg3ZPAidBAE7SrkLK>[cid:240f77ca-5cdb-40fb-b4c2-ee89a0eba1d4]ses.texi<https://1drv.ms/u/s!AkDIBBjRAOVwg3UshpzT9ZLCIiDf>.
Do you think it is OK ?
Concerning the ses-setq and change of ses-range, I realized that this makes a regression on ses-insert-range and ses-select, I have made a fix to ses-insert-range here : [cid:c43f099d-1b5e-4b57-a9f0-7feb40546350] ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3f1R7Le1n3L7qVe>, I still need to fix ses-select, since this is not a macro I use, it will take me some more time. Also, documenting this and writing tests is still needed before I merge my local dev branch to master.
Vincent.
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : lundi 20 novembre 2023 01:33
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: using ses programatically (was: a ses question)
Hi. Vincent.
I am going to reply both of your emails from this one.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Just to make my point more clear,
Vincent> with Calc you need to write '(float 12 -1) for 1.2, and use calcFunc-add instead of +,
Vincent> ie (apply 'calcFunc-add (ses-range N3 N6)). Also the cell printer should be
Vincent> math-format-value.
It sounds interesting to try.
Vincent> Note that with IEEE754 numbers ses+ is not so useful if you are using ses-range as you
Vincent> can delete blank by adding a ! argument, ie (apply 'ses+ (ses-range N3 N6)) is almost
Vincent> the same as (apply '+ (ses-range N3 N6 !)), the sole difference is that the former does
Vincent> the summing in revert order.
Well explained Vincent. Thanks for the explanation. I do not use ses
daily. So I discover ses (three years ago). And at that time
workbook.ses was created. From that time to now workbook.ses has been my
only contact with ses (with the exception of yesterday). Just changing
values, not formulae, formulaes has been almost the same from three
years ago. But Now that You have mentioned it. Three years ago I though
why using '+ when 'ses+ always take care of blanks. So that's the one to
use when using ses. Just until now You have showed me there is a
difference. So now the question could be "why using 'ses+ when '+ is
enough even for eliminating the blank values?"
It ended like this:
--8<---------------cut here---------------start------------->8---
(ses-setq :: sf N7 (apply '+ (ses-range N3 N6 !)))
--8<---------------cut here---------------end--------------->8---
Vincent> emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com> Objet :
Vincent> RE: using ses programatically (was: a ses question)
[...]
Vincent> Have you tried to use in both case '+ or 'ses+, but not '+ in one case and 'ses+ in the
Vincent> other case.
Well. Actually I started with the simple case just using '+ and after it
I replaced with the real formulae(which contained 'ses+) as the other ones within
workbook.ses. I am happy I had try it that way. So I have learn the
difference between 'ses+ and '+. It was a happy coincidence.
BTW.
s/"Compute the sum of the arguments, ignoring blanks."/"Compute the sum of the arguments in reverse order, ignoring blanks."
Could above be ok (for improving the documentation of 'ses+)?
Best Regards
Andrés Ramírez
[-- Attachment #1.2: Type: text/html, Size: 8050 bytes --]
[-- Attachment #2: Outlook-nvucxzxh.png --]
[-- Type: image/png, Size: 159 bytes --]
[-- Attachment #3: Outlook-fh4rwr0w.png --]
[-- Type: image/png, Size: 159 bytes --]
[-- Attachment #4: Outlook-jvdq1roe.png --]
[-- Type: image/png, Size: 159 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: using ses programatically (was: a ses question)
2023-12-24 11:51 ` Vincent Belaïche
@ 2023-12-24 15:44 ` andrés ramírez
2023-12-24 21:13 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: andrés ramírez @ 2023-12-24 15:44 UTC (permalink / raw)
To: Vincent Belaïche; +Cc: emacs-devel, boruch_baum@gmx.com
Hi. Vincent.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Hello Andrès,
Vincent> That is a good point that ses+ needs better documentation : I attached an update of
Vincent> ses.texi, [cid:55adc5ac-b103-461e-8604-536c90cae07a]
Vincent> ses.texi.diff<https://1drv.ms/u/s!AkDIBBjRAOVwg3ZPAidBAE7SrkLK>[cid:240f77ca-5cdb-40fb-b4c2-ee89a0eba1d4]ses.texi<https://1drv.ms/u/s!AkDIBBjRAOVwg3UshpzT9ZLCIiDf>.
Vincent> Do you think it is OK ?
The documentation change is Ok.
Vincent> Concerning the ses-setq and change of ses-range, I realized that this makes a
Vincent> regression on ses-insert-range and ses-select, I have made a fix to ses-insert-range
Vincent> here : [cid:c43f099d-1b5e-4b57-a9f0-7feb40546350]
Vincent> ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3f1R7Le1n3L7qVe>, I still need to fix
Vincent> ses-select, since this is not a macro I use, it will take me some more time. Also,
Vincent> documenting this and writing tests is still needed before I merge my local dev branch
Vincent> to master.
Take your time. And let me know when that part is completed.
Andrés Ramírez
ps: I have a second case (improvement) for discussion (about keyboard
macros and ses)
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: using ses programatically (was: a ses question)
2023-12-24 15:44 ` andrés ramírez
@ 2023-12-24 21:13 ` Vincent Belaïche
2023-12-27 17:42 ` Vincent Belaïche
0 siblings, 1 reply; 27+ messages in thread
From: Vincent Belaïche @ 2023-12-24 21:13 UTC (permalink / raw)
To: andrés ramírez; +Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 2142 bytes --]
Thank you Andrès for the feedback,
I have just pushed to master the improvement in ses+ documentation, and two other fixes. One is just an optimisation of ses-insert-row that was not really optimizing anything, and the other is about ses-formula-record, that was not recording anything, so the ' (ses-read-symbol) auto completion was not working.
Vincent.
PS : Now the head of my dev branch is this [https://res-h3.public.cdn.office.net/assets/mail/file-icon/png/generic_16x16.png] ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3hvsaDmTB8gD2ak>
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : dimanche 24 décembre 2023 16:44
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: using ses programatically (was: a ses question)
Hi. Vincent.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Hello Andrès,
Vincent> That is a good point that ses+ needs better documentation : I attached an update of
Vincent> ses.texi, [cid:55adc5ac-b103-461e-8604-536c90cae07a]
Vincent> ses.texi.diff<https://1drv.ms/u/s!AkDIBBjRAOVwg3ZPAidBAE7SrkLK>[cid:240f77ca-5cdb-40fb-b4c2-ee89a0eba1d4]ses.texi<https://1drv.ms/u/s!AkDIBBjRAOVwg3UshpzT9ZLCIiDf>.
Vincent> Do you think it is OK ?
The documentation change is Ok.
Vincent> Concerning the ses-setq and change of ses-range, I realized that this makes a
Vincent> regression on ses-insert-range and ses-select, I have made a fix to ses-insert-range
Vincent> here : [cid:c43f099d-1b5e-4b57-a9f0-7feb40546350]
Vincent> ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3f1R7Le1n3L7qVe>, I still need to fix
Vincent> ses-select, since this is not a macro I use, it will take me some more time. Also,
Vincent> documenting this and writing tests is still needed before I merge my local dev branch
Vincent> to master.
Take your time. And let me know when that part is completed.
Andrés Ramírez
ps: I have a second case (improvement) for discussion (about keyboard
macros and ses)
[-- Attachment #2: Type: text/html, Size: 4888 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: using ses programatically (was: a ses question)
2023-12-24 21:13 ` Vincent Belaïche
@ 2023-12-27 17:42 ` Vincent Belaïche
0 siblings, 0 replies; 27+ messages in thread
From: Vincent Belaïche @ 2023-12-27 17:42 UTC (permalink / raw)
To: andrés ramírez, christoph.conrad@gmx.de,
cyberbob@redneck.gacracker.org, syver-en@online.no,
fischman@zion.bpnetworks.com, Thomas.Gehrlein@t-online.de,
c.f.a.johnson@rogers.com, lyusong@hotmail.com, juri@jurta.org,
maierh@myself.com, anash@san.rr.com, pinard@iro.umontreal.ca,
ppinto@cs.cmu.edu, xsteve@riic.at, epameinondas@gmx.de,
rms@gnu.org, teirllm@dms.auburn.edu, jotto@pobox.com
Cc: emacs-devel, boruch_baum@gmx.com
[-- Attachment #1: Type: text/plain, Size: 3820 bytes --]
Hello Andrès and al.,
I write to all people listed in SES manual acknowledgements to know if anybody minds the proposed change to how ses-select works.
Here is an update (from my dev branch, nothing yet pushed), with ses-select fixed. Also ses-range does not directly inlines the implementation, but now delegates to a helper function ses-range-engine. ses-range-engine has an extra-argument value-extractor, this way, if one day we wish to make some ses-symbol-range macro to get cell symbols instead of cell values, it would be quite easy to define it as follows:
(defmacro ses-symbol-range (from to &rest rest)
`(ses-range-engine
#'ses-cell--symbol
(quote ,from) (quote ,to) ,(and rest `(quote ,rest))))
FYI information, the ses-select is now a function, no longer a macro, so it does not expand to a (list …) form containing symbols that by evaluation gets a list of values, but directly returns the list of values. I have no idea what the use of having this expansion to (list CELL-SYMBOLS) was, this seemed over-complex to me for no use. Also, ses-select used to revert the symbol order, and I have changed that too.
Any brickbats, questions, comments, etc… welcome,
Vincent.
[https://res-h3.public.cdn.office.net/assets/mail/file-icon/png/generic_16x16.png]ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3mnxH-UZJjXCV9n>
________________________________
De : Vincent Belaïche <vincent.b.1@hotmail.fr>
Envoyé : dimanche 24 décembre 2023 22:13
À : andrés ramírez <rrandresf@hotmail.com>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : RE: using ses programatically (was: a ses question)
Thank you Andrès for the feedback,
I have just pushed to master the improvement in ses+ documentation, and two other fixes. One is just an optimisation of ses-insert-row that was not really optimizing anything, and the other is about ses-formula-record, that was not recording anything, so the ' (ses-read-symbol) auto completion was not working.
Vincent.
PS : Now the head of my dev branch is this [https://res-h3.public.cdn.office.net/assets/mail/file-icon/png/generic_16x16.png] ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3hvsaDmTB8gD2ak>
________________________________
De : andrés ramírez <rrandresf@hotmail.com>
Envoyé : dimanche 24 décembre 2023 16:44
À : Vincent Belaïche <vincent.b.1@hotmail.fr>
Cc : emacs-devel <emacs-devel@gnu.org>; boruch_baum@gmx.com <boruch_baum@gmx.com>
Objet : Re: using ses programatically (was: a ses question)
Hi. Vincent.
>>>>> "Vincent" == Vincent Belaïche <vincent.b.1@hotmail.fr> writes:
Vincent> Hello Andrès,
Vincent> That is a good point that ses+ needs better documentation : I attached an update of
Vincent> ses.texi, [cid:55adc5ac-b103-461e-8604-536c90cae07a]
Vincent> ses.texi.diff<https://1drv.ms/u/s!AkDIBBjRAOVwg3ZPAidBAE7SrkLK>[cid:240f77ca-5cdb-40fb-b4c2-ee89a0eba1d4]ses.texi<https://1drv.ms/u/s!AkDIBBjRAOVwg3UshpzT9ZLCIiDf>.
Vincent> Do you think it is OK ?
The documentation change is Ok.
Vincent> Concerning the ses-setq and change of ses-range, I realized that this makes a
Vincent> regression on ses-insert-range and ses-select, I have made a fix to ses-insert-range
Vincent> here : [cid:c43f099d-1b5e-4b57-a9f0-7feb40546350]
Vincent> ses.el<https://1drv.ms/u/s!AkDIBBjRAOVwg3f1R7Le1n3L7qVe>, I still need to fix
Vincent> ses-select, since this is not a macro I use, it will take me some more time. Also,
Vincent> documenting this and writing tests is still needed before I merge my local dev branch
Vincent> to master.
Take your time. And let me know when that part is completed.
Andrés Ramírez
ps: I have a second case (improvement) for discussion (about keyboard
macros and ses)
[-- Attachment #2: Type: text/html, Size: 10452 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2023-12-27 17:42 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <SJ1PR12MB6363EAEDEA36DA78E736B9DEA61EA@SJ1PR12MB6363.namprd12.prod.outlook.com>
2023-10-29 16:43 ` a ses question Vincent Belaïche
2023-10-29 21:25 ` Vincent Belaïche
2023-10-30 5:43 ` Vincent Belaïche
2023-10-30 19:03 ` andrés ramírez
2023-11-01 19:08 ` Vincent Belaïche
2023-11-01 19:23 ` Vincent Belaïche
2023-11-02 11:20 ` Vincent Belaïche
2023-11-02 11:27 ` Vincent Belaïche
2023-11-02 11:31 ` Vincent Belaïche
2023-11-02 18:19 ` Stefan Monnier
2023-11-03 15:54 ` Vincent Belaïche
2023-11-03 22:13 ` Vincent Belaïche
2023-11-04 13:46 ` andrés ramírez
[not found] ` <SJ1PR12MB636334BD471403C3F936BF25A6A4A@SJ1PR12MB6363.namprd12.prod.outlook.com>
2023-11-05 10:25 ` using ses programatically (was: a ses question) Vincent Belaïche
2023-11-05 14:58 ` andrés ramírez
2023-11-05 16:55 ` Vincent Belaïche
2023-11-05 19:33 ` andrés ramírez
2023-11-18 22:55 ` Vincent Belaïche
2023-11-19 19:24 ` andrés ramírez
2023-11-19 23:18 ` Vincent Belaïche
2023-11-19 23:24 ` Vincent Belaïche
2023-11-20 0:33 ` andrés ramírez
2023-12-24 11:51 ` Vincent Belaïche
2023-12-24 15:44 ` andrés ramírez
2023-12-24 21:13 ` Vincent Belaïche
2023-12-27 17:42 ` Vincent Belaïche
2023-11-01 17:07 a ses question Andrés Ramírez
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).