c# - Defining a table rather than a range as a PivotTable 'cacheSource' -


i building tool automate creation of excel workbook contains table , associated pivottable. table structure on 1 sheet, data pulled database using tool @ later point. pivottable on second sheet using table previous sheet source.

i using epplus facilitate building tool running problems specifying cachesource. using following create range , pivottable:

 var datarange = dataworksheet.cells[dataworksheet.dimension.address.tostring()];   var pivottable = pivotworksheet.pivottables.add(pivotworksheet.cells["b3"], datarange, name); 

this sets cachesource to:

<x:cachesource type="worksheet" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> <x:worksheetsource ref="a1:x2" sheet="dataworksheet" /> 

or within excel, data source set to:

dataworksheet!$a$1:$x$2 

this works fine if table size never changes, number of rows dynamic, finding when data refreshed, data read initial range specified.

what want programmatically set cachesource to:

<x:cachesource type="worksheet" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">   <x:worksheetsource name="dataworksheet" /> </x:cachesource> 

or in excel, set data source to:

dataworksheet 

i believe may possible accessing xml directly (any pointers on welcome) there way using epplus?

it can done not prettiest thing in world. can extract cache def xml , edit created epplus pivot table object wreak havoc save logic when call package.save() (or getasbytearray()) since parses xml on save generate final file. result of, said, epplus not capable of handling table source.

so, alternative save file epplus , manipulate content of xlsx renamed zip file using .net ziparchive. trick cannot manipulate files out of order in zip otherwise excel complain when opens file. , since cannot insert entry (only add end) have recreate zip. here extension method on ziparchive allow update cache source:

public static bool setcachesourcetotable(this ziparchive xlsxzip, fileinfo destinationfileinfo, string tablename, int cachesourcenumber = 1) {     var cachefound = false;     var cachename = string.format("pivotcachedefinition{0}.xml", cachesourcenumber);      using (var copiedzip = new ziparchive(destinationfileinfo.open(filemode.create, fileaccess.readwrite), ziparchivemode.update))     {         //go though each file in zip 1 one , copy on new file - entries need in order         xlsxzip.entries.tolist().foreach(entry =>         {             var newentry = copiedzip.createentry(entry.fullname);             var newstream = newentry.open();             var orgstream = entry.open();              //copy other files except cache def after             if (entry.name != cachename)             {                 orgstream.copyto(newstream);             }             else             {                 cachefound = true;                  //load xml document manipulate                 var xdoc = new xmldocument();                 xdoc.load(orgstream);                  //get reference worksheet xml proper namespace                 var nsm = new xmlnamespacemanager(xdoc.nametable);                 nsm.addnamespace("default", xdoc.documentelement.namespaceuri);                  //get source                 var worksheetsource = xdoc.selectsinglenode("/default:pivotcachedefinition/default:cachesource/default:worksheetsource", nsm);                  //clear attributes                 var att = worksheetsource.attributes["ref"];                 worksheetsource.attributes.remove(att);                  att = worksheetsource.attributes["sheet"];                 worksheetsource.attributes.remove(att);                  //create new attribute table                 att = xdoc.createattribute("name");                 att.value = tablename;                 worksheetsource.attributes.append(att);                  xdoc.save(newstream);             }              orgstream.close();             newstream.flush();             newstream.close();         });     }      return cachefound;  } 

and here how use it:

//throw in data var datatable = new datatable("tbldata"); datatable.columns.addrange(new[] {     new datacolumn("col1", typeof (int)), new datacolumn("col2", typeof (int)), new datacolumn("col3", typeof (object)) });  (var = 0; < 10; i++) {     var row = datatable.newrow();     row[0] = i; row[1] = i*10; row[2] = path.getrandomfilename();     datatable.rows.add(row); }  const string tablename = "pivottablesource"; using (var pck = new excelpackage()) {     var workbook = pck.workbook;      var source = workbook.worksheets.add("source");     source.cells.loadfromdatatable(datatable, true);     var datacells = source.cells["a1:c11"];      source.tables.add(datacells, tablename);      var pivotsheet = workbook.worksheets.add("pivot");     pivotsheet.pivottables.add(pivotsheet.cells["a1"], datacells, "pivottable1");      using (var orginalzip = new ziparchive(new memorystream(pck.getasbytearray()), ziparchivemode.read))     {         var fi = new fileinfo(@"c:\temp\pivot_from_table.xlsx");         if (fi.exists)             fi.delete();           var result = orginalzip.setcachesourcetotable(fi, tablename, 1);         console.write("cache source updated: ");         console.write(result);     } } 

Comments

Popular posts from this blog

php - Invalid Cofiguration - yii\base\InvalidConfigException - Yii2 -

How to show in django cms breadcrumbs full path? -

ruby on rails - npm error: tunneling socket could not be established, cause=connect ETIMEDOUT -