|  | @@ -47,19 +47,26 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ; the order goes top to bottom, then left to right - that makes the most sense to me
 | 
	
		
			
				|  |  |  ; I don't know why a different order would be important, or even in what situation order is important at all
 | 
	
		
			
				|  |  | -(def parse-range
 | 
	
		
			
				|  |  | +(defn parse-range
 | 
	
		
			
				|  |  | +  "Converts a range in \"A1:B2\" notation to a comma-separated list of cells: \"A1,A2,B1,B2\"."
 | 
	
		
			
				|  |  | +  [range-string]
 | 
	
		
			
				|  |  | +  (let [col1 (second (re-find #"\(\s*([A-Z]+)" range-string))
 | 
	
		
			
				|  |  | +        col2 (second (re-find #":\s*([A-Z]+)" range-string))
 | 
	
		
			
				|  |  | +        row1 (.parseInt js/window (second (re-find #"([0-9]+)\s*:" range-string)))
 | 
	
		
			
				|  |  | +        row2 (.parseInt js/window (second (re-find #"([0-9]+)\s*\)" range-string)))
 | 
	
		
			
				|  |  | +        [start-col end-col] (order-two-cols col1 col2)
 | 
	
		
			
				|  |  | +        start-row (min row1 row2)
 | 
	
		
			
				|  |  | +        end-row (max row1 row2)]
 | 
	
		
			
				|  |  | +    (for [col (take-while #(not= (next-letter end-col) %) (iterate next-letter start-col))
 | 
	
		
			
				|  |  | +             row (range start-row (inc end-row))]
 | 
	
		
			
				|  |  | +         {:col col :row row})))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +(def range->commalist
 | 
	
		
			
				|  |  |    "Converts a range in \"A1:B2\" notation to a comma-separated list of cells: \"A1,A2,B1,B2\"."
 | 
	
		
			
				|  |  |    (memoize (fn [range-string]
 | 
	
		
			
				|  |  | -             (let [col1 (second (re-find #"\(\s*([A-Z]+)" range-string))
 | 
	
		
			
				|  |  | -                   col2 (second (re-find #":\s*([A-Z]+)" range-string))
 | 
	
		
			
				|  |  | -                   row1 (.parseInt js/window (second (re-find #"([0-9]+)\s*:" range-string)))
 | 
	
		
			
				|  |  | -                   row2 (.parseInt js/window (second (re-find #"([0-9]+)\s*\)" range-string)))
 | 
	
		
			
				|  |  | -                   [start-col end-col] (order-two-cols col1 col2)
 | 
	
		
			
				|  |  | -                   start-row (min row1 row2)
 | 
	
		
			
				|  |  | -                   end-row (max row1 row2)]
 | 
	
		
			
				|  |  | -               (str "(" (clojure.string/join "," (for [col (take-while #(not= (next-letter end-col) %) (iterate next-letter start-col))
 | 
	
		
			
				|  |  | -                                                       row (range start-row (inc end-row))]
 | 
	
		
			
				|  |  | -                                                  (str col row))) ")")))))
 | 
	
		
			
				|  |  | +            (let [cell-list (parse-range range-string)
 | 
	
		
			
				|  |  | +                  strings (map #(str (:col %) (:row %)) cell-list)]
 | 
	
		
			
				|  |  | +             (str "(" (clojure.string/join "," strings) ")")))))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  (def replace-ranges-in-expression
 | 
	
		
			
				|  |  |    "Receives an expression string, and replaces all ranges in colon notation (\"A1:B2\") into a comma-separated list of cells (\"A1,A2,B1,B2\")."
 | 
	
	
		
			
				|  | @@ -161,7 +168,7 @@
 | 
	
		
			
				|  |  |    "Assuming all references have been added, insert all back references."
 | 
	
		
			
				|  |  |    [data]
 | 
	
		
			
				|  |  |    (loop [data data
 | 
	
		
			
				|  |  | -         formulas (walk-get-refs data formula?)]
 | 
	
		
			
				|  |  | +         formulas (walk-get-refs data #(formula? (:value %3)))]
 | 
	
		
			
				|  |  |      (if (empty? formulas)
 | 
	
		
			
				|  |  |        data
 | 
	
		
			
				|  |  |        (let [origin (first formulas)
 | 
	
	
		
			
				|  | @@ -274,7 +281,7 @@
 | 
	
		
			
				|  |  |          cycle-refs (some #(= (:display %) :cycle-error) resolved-refs)
 | 
	
		
			
				|  |  |          disqualified? (or invalid-refs dirty-refs error-refs)]
 | 
	
		
			
				|  |  |      (cond
 | 
	
		
			
				|  |  | -      formula (assoc-in data [c r] datum)           ; if it's not a formula, then return as is (with the dirty flag removed)
 | 
	
		
			
				|  |  | +      (not formula) (assoc-in data [c r] datum)     ; if it's not a formula, then return as is (with the dirty flag removed)
 | 
	
		
			
				|  |  |        cycle-refs (-> data                           ; if one of its references has a reference cycle, then this one is "poisoned" as well
 | 
	
		
			
				|  |  |                       (assoc-in [c r] datum)
 | 
	
		
			
				|  |  |                       (assoc-in [c r :display] :cycle-error))
 |