1package sheet23import "testing"45func bold(st *Style) { st.Bold = true }67// Copying whole columns and pasting them at the top of a column carries8// the column formats themselves: no cells are made for them, and the9// paste undoes as one step.10func TestCopyWholeColumnsCarriesFormats(t *testing.T) {11 s := New()12 s.Set(at("B1"), "5")13 s.Set(at("B2"), "6")14 s.SetFormat(col(1), Preset(FmtCurrency))15 s.SetStyle(at1("B2"), bold)16 s.SetFormat(col(3), Preset(FmtPercent)) // D, to be replaced17 s.SetStyle(rowRect(4, 4), func(st *Style) { st.Italic = true })18 cells := s.cells.len()1920 dst, err := s.Paste(s.Copy(col(1)), at1("D1"), false)21 if err != nil || dst != col(3) {22 t.Fatalf("pasted at %v, %v; want D:D", dst, err)23 }24 if f := s.lines.cols[3].Format; f.Kind != FmtCurrency {25 t.Errorf("column D's format = %v, want currency", f.Kind)26 }27 for _, a := range []string{"D1", "D2", "D900000"} {28 if f := s.DisplayFormat(at(a)); f.Kind != FmtCurrency {29 t.Errorf("%s shows %v, want currency", a, f.Kind)30 }31 }32 if !s.CellStyle(at("D2")).Bold || s.CellStyle(at("D3")).Bold {33 t.Error("B2's bold didn't travel to D2 alone")34 }35 if !s.CellStyle(at("D5")).Italic {36 t.Error("row 5's italic is lost where it crosses column D")37 }38 if n := s.cells.len(); n != cells+2 {39 t.Errorf("%d cells after the paste, want %d: only B1 and B2's copies", n, cells+2)40 }41 s.Undo()42 if f := s.DisplayFormat(at("D9")); f.Kind != FmtPercent {43 t.Errorf("after undo D9 shows %v, want percent again", f.Kind)44 }45 if s.cells.get(at("D1")) != nil {46 t.Error("undo left D1")47 }4849 // Pasted anywhere else, the copy is a block of cells showing what50 // the column showed.51 if _, err := s.Paste(s.Copy(col(1)), at1("F5"), false); err != nil {52 t.Fatal(err)53 }54 if s.DisplayFormat(at("F6")).Kind != FmtCurrency || !s.CellStyle(at("F6")).Bold || s.lines.cols[5] != (lineFmt{}) {55 t.Errorf("F6 shows %v bold %v; column F %+v", s.DisplayFormat(at("F6")).Kind, s.CellStyle(at("F6")).Bold, s.lines.cols[5])56 }57 if f := s.DisplayFormat(at("F7")); !f.IsZero() {58 t.Errorf("F7 shows %v, past the copied cells", f.Kind)59 }60}6162// Whole rows carry their row formats, and filling whole rows down63// copies the row's format to the rows filled.64func TestCopyWholeRowsCarriesFormats(t *testing.T) {65 s := New()66 s.Set(at("A2"), "1")67 s.SetStyle(rowRect(1, 1), bold)68 if _, err := s.Paste(s.Copy(rowRect(1, 1)), at1("A7"), false); err != nil {69 t.Fatal(err)70 }71 if !s.lines.rows[6].Style.Bold || s.Value(at("A7")).Num != 1 {72 t.Errorf("row 7 = %+v, A7 = %v", s.lines.rows[6], s.Value(at("A7")))73 }74 if _, err := s.FillDown(rowRect(6, 9)); err != nil {75 t.Fatal(err)76 }77 if !s.lines.rows[9].Style.Bold || !s.CellStyle(at("ZZ10")).Bold {78 t.Errorf("fill down didn't carry row 7's bold to row 10: %+v", s.lines.rows[9])79 }80}8182// A block pasted into cells shows the formats its source cells showed,83// from their own, their row's, column's or the sheet's, and replaces84// the formats of the lines it lands on.85func TestPasteBlockAppliesEffectiveFormats(t *testing.T) {86 s := New()87 s.Set(at("A1"), "1")88 s.SetFormat(col(0), Preset(FmtCurrency))89 s.SetStyle(rowRect(1, 1), bold)90 s.SetFormat(col(4), Preset(FmtPercent)) // E91 s.Set(at("G1"), "2") // plain9293 if _, err := s.Paste(s.Copy(Rect{From: at("A1"), To: at("A3")}), at1("C1"), false); err != nil {94 t.Fatal(err)95 }96 for _, a := range []string{"C1", "C2", "C3"} {97 if f := s.DisplayFormat(at(a)); f.Kind != FmtCurrency {98 t.Errorf("%s shows %v, want currency", a, f.Kind)99 }100 }101 if !s.CellStyle(at("C2")).Bold {102 t.Error("C2 lost row 2's bold")103 }104 if f := s.DisplayFormat(at("C4")); !f.IsZero() {105 t.Errorf("C4 shows %v, past the paste", f.Kind)106 }107108 // Plain cells pasted into a percent column show plain, as their109 // source did.110 if _, err := s.Paste(s.Copy(Rect{From: at("G1"), To: at("G2")}), at1("E1"), false); err != nil {111 t.Fatal(err)112 }113 if f := s.DisplayFormat(at("E1")); !f.IsZero() {114 t.Errorf("E1 shows %v, want the plain format it was copied with", f.Kind)115 }116 if f := s.DisplayFormat(at("E5")); f.Kind != FmtPercent {117 t.Errorf("E5 shows %v, want its column's percent", f.Kind)118 }119120 // Pasting values only keeps the destination's formats.121 if _, err := s.Paste(s.Copy(at1("G1")), at1("E7"), true); err != nil {122 t.Fatal(err)123 }124 if f := s.DisplayFormat(at("E7")); f.Kind != FmtPercent {125 t.Errorf("E7 shows %v after pasting values, want percent", f.Kind)126 }127}128129// Cutting whole columns moves their formats, leaving the source plain;130// a cut block takes the formats its cells showed.131func TestMoveCarriesFormats(t *testing.T) {132 w := NewBook()133 s := w.Sheets()[0]134 s.Set(at("B1"), "5")135 s.SetFormat(col(1), Preset(FmtCurrency))136 c := s.Copy(col(1))137 if r := c.MoveRange(at("F1")); r != col(1) {138 t.Fatalf("a cut of B:B pasted at F1 moves %v", r)139 }140 if r := c.MoveRange(at("F3")); r != at1("B1") {141 t.Fatalf("a cut of B:B pasted at F3 moves %v", r)142 }143 if _, err := s.Move(col(1), at("F1")); err != nil {144 t.Fatal(err)145 }146 if s.DisplayFormat(at("F9")).Kind != FmtCurrency || !s.DisplayFormat(at("B9")).IsZero() {147 t.Errorf("after moving B:B to F:F, F9 shows %v and B9 %v", s.DisplayFormat(at("F9")).Kind, s.DisplayFormat(at("B9")).Kind)148 }149 s.Undo()150 if s.DisplayFormat(at("B9")).Kind != FmtCurrency || !s.DisplayFormat(at("F9")).IsZero() {151 t.Error("undo didn't bring column B's format back")152 }153154 // To another sheet.155 o, _ := w.AddSheet("Other", 1)156 if _, err := s.MoveTo(o, col(1), at("C1")); err != nil {157 t.Fatal(err)158 }159 if o.DisplayFormat(at("C1")).Kind != FmtCurrency || o.Value(at("C1")).Num != 5 || !s.DisplayFormat(at("B1")).IsZero() {160 t.Errorf("Other!C1 shows %v %v; B1 %v", o.DisplayFormat(at("C1")).Kind, o.Value(at("C1")), s.DisplayFormat(at("B1")).Kind)161 }162163 // A block keeps its formats; the source is left plain, as Sheets164 // clears cut cells, though its column stays currency.165 o.Set(at("C2"), "7")166 if _, err := o.MoveTo(s, Rect{From: at("C1"), To: at("C2")}, at("E4")); err != nil {167 t.Fatal(err)168 }169 if s.DisplayFormat(at("E5")).Kind != FmtCurrency || !o.DisplayFormat(at("C1")).IsZero() || o.DisplayFormat(at("C3")).Kind != FmtCurrency {170 t.Errorf("E5 shows %v, Other!C1 %v, Other!C3 %v", s.DisplayFormat(at("E5")).Kind, o.DisplayFormat(at("C1")).Kind, o.DisplayFormat(at("C3")).Kind)171 }172}173174// Cutting a block on its sheet leaves the cells it left plain, over175// formatted columns and rows, except where it lands; undo restores them.176func TestMoveBlockLeavesSourcePlain(t *testing.T) {177 s := New()178 s.SetFormat(col(1), Preset(FmtCurrency))179 s.SetStyle(rowRect(1, 1), bold) // row 2180 s.Set(at("B1"), "5")181 s.Set(at("B2"), "6")182 s.Set(at("C3"), "7")183 if _, err := s.Move(Rect{From: at("B1"), To: at("C3")}, at("C2")); err != nil {184 t.Fatal(err)185 }186 for _, a := range []string{"B1", "B2", "B3", "C1"} {187 if !s.DisplayFormat(at(a)).IsZero() || s.CellStyle(at(a)).Bold {188 t.Errorf("%s shows %v, bold %v, want plain", a, s.DisplayFormat(at(a)).Kind, s.CellStyle(at(a)).Bold)189 }190 }191 if s.DisplayFormat(at("C2")).Kind != FmtCurrency || s.DisplayFormat(at("B4")).Kind != FmtCurrency || !s.CellStyle(at("A2")).Bold {192 t.Errorf("C2 %v (moved from B1), B4 %v, A2 bold %v", s.DisplayFormat(at("C2")).Kind, s.DisplayFormat(at("B4")).Kind, s.CellStyle(at("A2")).Bold)193 }194 s.Undo()195 if s.DisplayFormat(at("B3")).Kind != FmtCurrency || !s.CellStyle(at("B2")).Bold || s.cells.get(at("B3")) != nil {196 t.Errorf("undo: B3 %v, B2 bold %v", s.DisplayFormat(at("B3")).Kind, s.CellStyle(at("B2")).Bold)197 }198}199200// Pasting a column format re-infers formulas reading the column's blanks.201func TestPasteColumnReinfers(t *testing.T) {202 s := New()203 s.SetFormat(col(0), Preset(FmtCurrency))204 s.Set(at("C1"), "=D5*2")205 if _, err := s.Paste(s.Copy(col(0)), at1("D1"), false); err != nil {206 t.Fatal(err)207 }208 if f := s.DisplayFormat(at("C1")); f.Kind != FmtCurrency {209 t.Errorf("C1 shows %v, want currency from column D", f.Kind)210 }211}