12
12
package excelize
13
13
14
14
import (
15
+ "encoding/xml"
15
16
"fmt"
16
17
"io"
17
18
"math"
19
+ "slices"
18
20
"strings"
19
21
"unicode/utf16"
20
22
)
@@ -344,9 +346,6 @@ func getDataValidations(dvs *xlsxDataValidations) []*DataValidation {
344
346
Sqref : dv .Sqref ,
345
347
Type : dv .Type ,
346
348
}
347
- if dv .ExtLst != nil {
348
- dataValidation .ExtLstXML = dv .ExtLst .Ext
349
- }
350
349
if dv .Formula1 != nil {
351
350
dataValidation .Formula1 = unescapeDataValidationFormula (dv .Formula1 .Content )
352
351
}
@@ -364,27 +363,59 @@ func getDataValidations(dvs *xlsxDataValidations) []*DataValidation {
364
363
}
365
364
366
365
// DeleteDataValidation delete data validation by given worksheet name and
367
- // reference sequence. This function is concurrency safe.
368
- // All data validations in the worksheet will be deleted
369
- // if not specify reference sequence parameter.
366
+ // reference sequence. This function is concurrency safe. All data validations
367
+ // in the worksheet will be deleted if not specify reference sequence parameter.
368
+ //
369
+ // Example 1, delete data validation on Sheet1!A1:B2:
370
+ //
371
+ // err := f.DeleteDataValidation("Sheet1", "A1:B2")
372
+ //
373
+ // Example 2, delete data validations on Sheet1 with multiple cell ranges
374
+ // A1:B2 and C1:C3 with reference sequence slice:
375
+ //
376
+ // err := f.DeleteDataValidation("Sheet1", []string{"A1:B2", "C1:C3"}...)
377
+ //
378
+ // Example 3, delete data validations on Sheet1 with multiple cell ranges
379
+ // A1:B2 and C1:C3 with blank separated reference sequence string, the result
380
+ // same as example 2:
381
+ //
382
+ // err := f.DeleteDataValidation("Sheet1", "A1:B2 C1:C3")
383
+ //
384
+ // Example 4, delete all data validations on Sheet1:
385
+ //
386
+ // err := f.DeleteDataValidation("Sheet1")
370
387
func (f * File ) DeleteDataValidation (sheet string , sqref ... string ) error {
371
388
ws , err := f .workSheetReader (sheet )
372
389
if err != nil {
373
390
return err
374
391
}
375
392
ws .mu .Lock ()
376
393
defer ws .mu .Unlock ()
377
- if ws .DataValidations == nil {
394
+ if ws .DataValidations == nil && ws . ExtLst == nil {
378
395
return nil
379
396
}
380
397
if sqref == nil {
381
398
ws .DataValidations = nil
382
399
return nil
383
400
}
384
- delCells , err := flatSqref (sqref [ 0 ] )
401
+ delCells , err := flatSqref (strings . Join ( sqref , " " ) )
385
402
if err != nil {
386
403
return err
387
404
}
405
+ if ws .DataValidations != nil {
406
+ if err = f .deleteDataValidation (ws , delCells ); err != nil {
407
+ return err
408
+ }
409
+ }
410
+ if ws .ExtLst != nil {
411
+ return f .deleteX14DataValidation (ws , sqref )
412
+ }
413
+ return nil
414
+ }
415
+
416
+ // deleteDataValidation deletes data validation by given worksheet and cell
417
+ // reference list.
418
+ func (f * File ) deleteDataValidation (ws * xlsxWorksheet , delCells map [int ][][]int ) error {
388
419
dv := ws .DataValidations
389
420
for i := 0 ; i < len (dv .DataValidation ); i ++ {
390
421
var applySqref []string
@@ -416,6 +447,64 @@ func (f *File) DeleteDataValidation(sheet string, sqref ...string) error {
416
447
return nil
417
448
}
418
449
450
+ // deleteX14DataValidation deletes data validation in the extLst element by
451
+ // given worksheet and cell reference list.
452
+ func (f * File ) deleteX14DataValidation (ws * xlsxWorksheet , sqref []string ) error {
453
+ var (
454
+ decodeExtLst = new (decodeExtLst )
455
+ decodeDataValidations * xlsxDataValidations
456
+ x14DataValidations * xlsxX14DataValidations
457
+ )
458
+ if err := f .xmlNewDecoder (strings .NewReader ("<extLst>" + ws .ExtLst .Ext + "</extLst>" )).
459
+ Decode (decodeExtLst ); err != nil && err != io .EOF {
460
+ return err
461
+ }
462
+ for i , ext := range decodeExtLst .Ext {
463
+ if ext .URI == ExtURIDataValidations {
464
+ decodeDataValidations = new (xlsxDataValidations )
465
+ x14DataValidations = new (xlsxX14DataValidations )
466
+ _ = f .xmlNewDecoder (strings .NewReader (ext .Content )).Decode (decodeDataValidations )
467
+ x14DataValidations .XMLNSXM = NameSpaceSpreadSheetExcel2006Main .Value
468
+ x14DataValidations .DisablePrompts = decodeDataValidations .DisablePrompts
469
+ x14DataValidations .XWindow = decodeDataValidations .XWindow
470
+ x14DataValidations .YWindow = decodeDataValidations .YWindow
471
+ for _ , dv := range decodeDataValidations .DataValidation {
472
+ if inStrSlice (sqref , dv .XMSqref , false ) == - 1 {
473
+ x14DataValidations .DataValidation = append (x14DataValidations .DataValidation , & xlsxX14DataValidation {
474
+ AllowBlank : dv .AllowBlank ,
475
+ Error : dv .Error ,
476
+ ErrorStyle : dv .ErrorStyle ,
477
+ ErrorTitle : dv .ErrorTitle ,
478
+ Operator : dv .Operator ,
479
+ Prompt : dv .Prompt ,
480
+ PromptTitle : dv .PromptTitle ,
481
+ ShowDropDown : dv .ShowDropDown ,
482
+ ShowErrorMessage : dv .ShowErrorMessage ,
483
+ ShowInputMessage : dv .ShowInputMessage ,
484
+ Sqref : dv .Sqref ,
485
+ XMSqref : dv .XMSqref ,
486
+ Type : dv .Type ,
487
+ Formula1 : dv .Formula1 ,
488
+ Formula2 : dv .Formula2 ,
489
+ })
490
+ }
491
+ }
492
+ x14DataValidations .Count = len (x14DataValidations .DataValidation )
493
+ x14DataValidationsBytes , _ := xml .Marshal (x14DataValidations )
494
+ decodeExtLst .Ext [i ] = & xlsxExt {
495
+ xmlns : []xml.Attr {{Name : xml.Name {Local : "xmlns:" + NameSpaceSpreadSheetX14 .Name .Local }, Value : NameSpaceSpreadSheetX14 .Value }},
496
+ URI : ExtURIDataValidations , Content : string (x14DataValidationsBytes ),
497
+ }
498
+ if x14DataValidations .Count == 0 {
499
+ decodeExtLst .Ext = slices .Delete (decodeExtLst .Ext , i , i + 1 )
500
+ }
501
+ }
502
+ }
503
+ extLstBytes , err := xml .Marshal (decodeExtLst )
504
+ ws .ExtLst = & xlsxExtLst {Ext : strings .TrimSuffix (strings .TrimPrefix (string (extLstBytes ), "<extLst>" ), "</extLst>" )}
505
+ return err
506
+ }
507
+
419
508
// squashSqref generates cell reference sequence by given cells coordinates list.
420
509
func squashSqref (cells [][]int ) []string {
421
510
if len (cells ) == 1 {
0 commit comments