Skip to content

Commit

Permalink
Updating examples to show new features
Browse files Browse the repository at this point in the history
Fix shared charts to use explicit value as expressions will leave values empty.
Add DR chart resize to shared charts.

Show HTML/DOCX embedding in Word.

Add Content Control Dropdown example to XML binding.

DR Chart example added to SheetReport.

Alternative way to present empty table in WordTables
  • Loading branch information
zapov committed Sep 9, 2021
1 parent f40e8e9 commit 2bd7bac
Show file tree
Hide file tree
Showing 46 changed files with 418 additions and 127 deletions.
2 changes: 2 additions & 0 deletions Advanced/PowerQuery/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ But if we want CSV files to remain in the Excel we need to slighly modify the xl

These steps will prevent Excel from removing the CSV file on further saves.

**Alternatively embedded CSV files can be managed via Templater Editor in which case there is no need for this manual setup.**

### Consuming CSV from PowerQuery

To load CSV into PowerQuery two more pieces are required:
Expand Down
7 changes: 6 additions & 1 deletion Advanced/SheetReport/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ Sheet duplication can be done in two ways; by using clone (which will duplicate
Sheet will be duplicate at appropriate index (meaning for sheet resize there can be other sheets after it).
If sheet tag is not replaced sheet will have a generic name.

### Charts with Dynamic Resize

When charts have unknown number of series, they can be populated via Dynamic Resize.
This can be done via 2 or 3 tags (as same tag can be used for categories and values).

### Utilizing Excel features

While table on specific sheet is not hidden, it could be put in columns without width so it would look like it's not there.
Other tricks could also be used to make more user friendly report.
Other tricks could also be used to make more user friendly report.
Binary file modified Advanced/SheetReport/result.xlsx
Binary file not shown.
47 changes: 40 additions & 7 deletions Advanced/SheetReport/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private static InputData LoadXml()
var entry = zip.GetEntry("UNdata_Export.xml");
var xml = XElement.Load(zip.GetInputStream(entry.ZipFileIndex));
zip.Close();
var result = new InputData();
var result = new InputData(6);
var lastCountry = string.Empty;
CountryInfo country = new CountryInfo();
var cities = new Dictionary<string, RawData>();
Expand Down Expand Up @@ -71,28 +71,61 @@ class InputData
{
public List<RawData> data = new List<RawData>();
public List<CountryInfo> country = new List<CountryInfo>();
public string[][] cities;

public InputData(int size)
{
cities = new string[1][];
cities[0] = new string[size];
for (int i = 0; i < size; i++)
cities[0][i] = Order[i] + " city";
}

public object[,] analysis()
{
var size = cities[0].Length;
var result = new object[country.Count, size + 1];
for (int i = 0; i < country.Count; i++)
{
var c = country[i];
var sorted = c.city.OrderByDescending(it => it.population).ToArray();
result[i, 0] = c.name;
for (int j = 1; j <= size && j <= sorted.Length; j++)
result[i, j] = sorted[j - 1].population;
}
return result;
}
}
private static string[] Order = new string[]{
"Largest",
"Second",
"Third",
"Fourth",
"Fifth",
"Sixth",
"Seventh",
};

class RawData
{
public String country;
public String city;
public string country;
public string city;
public int year;
public long population;
}

class CityData
{
public String name;
public string name;
public long population;
}

class CountryInfo
{
public String name;
//In this case, Tenplater doesn't cope with same tag twice, so let's put tag for the sheet into a separate tag
public string name;
//In this case, Templater doesn't cope with same tag twice, so let's put tag for the sheet into a separate tag
//also, sheet name can't be longer than 31 characters
public String sheetName() { return name.Substring(0, Math.Min(30, name.Length)); }
public string sheetName() { return name.Substring(0, Math.Min(30, name.Length)); }
public List<CityData> city = new List<CityData>();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@

public class SheetReportExample {

public static void main(final String[] args) throws Exception {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
InputStream templateStream = SheetReportExample.class.getResourceAsStream("/Report.xlsx");
File tmp = File.createTempFile("table", ".xlsx");

FileOutputStream fos = new FileOutputStream(tmp);
ITemplateDocument tpl = Configuration.factory().open(templateStream, "xlsx", fos);

InputData data = loadXml(dbFactory);

tpl.process(data);

tpl.close();
fos.close();
Desktop.getDesktop().open(tmp);
}

private static String getValue(NodeList xml, String attribute) {
for (int i = 0; i < xml.getLength(); i++) {
Element item = (Element) xml.item(i);
Expand All @@ -26,7 +43,7 @@ private static String getValue(NodeList xml, String attribute) {
}

private static InputData loadXml(DocumentBuilderFactory dbf) throws Exception {
InputData result = new InputData();
InputData result = new InputData(6);
InputStream input = SheetReportExample.class.getResourceAsStream("/UNdata_Export.zip");
ZipInputStream zip = new ZipInputStream(input);
ZipEntry entry = zip.getNextEntry();
Expand Down Expand Up @@ -86,46 +103,61 @@ private static InputData loadXml(DocumentBuilderFactory dbf) throws Exception {
return result;
}

public static void main(final String[] args) throws Exception {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
InputStream templateStream = SheetReportExample.class.getResourceAsStream("/Report.xlsx");
File tmp = File.createTempFile("table", ".xlsx");

FileOutputStream fos = new FileOutputStream(tmp);
ITemplateDocument tpl = Configuration.factory().open(templateStream, "xlsx", fos);

InputData data = loadXml(dbFactory);

tpl.process(data);
public static class InputData {
public List<RawData> data = new ArrayList<>();
public List<CountryInfo> country = new ArrayList<>();
public String[][] cities;

tpl.close();
fos.close();
Desktop.getDesktop().open(tmp);
}
public InputData(int size) {
cities = new String[1][];
cities[0] = new String[size];
for (int i = 0; i < size; i++) {
cities[0][i] = ORDER[i] + " city";
}
}

static class InputData {
public List<RawData> data = new ArrayList<RawData>();
public List<CountryInfo> country = new ArrayList<CountryInfo>();
public Object[][] analysis() {
int size = cities[0].length;
Object[][] result = new Object[country.size()][size + 1];
for (int i = 0; i < country.size(); i++) {
CountryInfo c = country.get(i);
CityData[] sorted = c.city.stream().sorted(Comparator.comparingLong(it -> -it.population)).toArray(CityData[]::new);
result[i][0] = c.name;
for (int j = 1; j <= size && j <= sorted.length; j++) {
result[i][j] = sorted[j - 1].population;
}
}
return result;
}
}
private static String[] ORDER = {
"Largest",
"Second",
"Third",
"Fourth",
"Fifth",
"Sixth",
"Seventh",
};

static class RawData {
public static class RawData {
public String country;
public String city;
public int year;
public long population;
}

static class CityData {
public static class CityData {
public String name;
public long population;
}

static class CountryInfo {
public static class CountryInfo {
public String name;
//In this case, Tenplater doesn't cope with same tag twice, so let's put tag for the sheet into a separate tag
//In this case, Templater doesn't cope with same tag twice, so let's put tag for the sheet into a separate tag
//also, sheet name can't be longer than 31 characters
public String sheetName() { return name.substring(0, Math.min(30, name.length())); }
public List<CityData> city = new ArrayList<CityData>();
public List<CityData> city = new ArrayList<>();
}

}
Binary file modified Advanced/SheetReport/template/Report.xlsx
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -274,18 +274,24 @@ private byte[] processTemplate(final byte[] templateBytes, final Object data, fi
IDocumentFactory factory = asSchema ? schemaFactory : debugLog ? debugFactory : documentFactory;
IDocumentFactory.CancellationToken cancellationToken = new IDocumentFactory.CancellationToken() {
private final long runUntil = System.currentTimeMillis() + timeoutLimit * 1000L;

@Override
public boolean isCanceled() {
//if processing does not finish within specified timeout (default 30 seconds), cancel the run
//when operation is canceled CancellationException is thrown
return timeoutLimit > 0 && System.currentTimeMillis() > runUntil;
}
};
try(ITemplateDocument doc = factory.open(is, ext, baos, cancellationToken)) {
try (ITemplateDocument doc = factory.open(is, ext, baos, cancellationToken)) {
doc.process(data);
}
status = "success";
return baos.toByteArray();
} catch (Throwable ex) {
if (logger.isLoggable(Level.SEVERE)) {
logger.log(Level.SEVERE, ex.getMessage());
}
throw ex;
} finally {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, String.format("Templater processed (%s) in %d ms. Status = %s", ext, new Date().getTime() - start, status));
Expand Down Expand Up @@ -497,6 +503,9 @@ public void handle(HttpExchange httpExchange) throws IOException {
} catch (CancellationException e) {
sendResponse(httpExchange, 429, MIME_PLAINTEXT, "Processing the request took too long. Processing canceled", start);
return;
} catch (Exception e) {
sendResponse(httpExchange, 500, MIME_PLAINTEXT, "Error processing the request", start);
return;
}
sendResponse(httpExchange, 200, mime, template, start);
return;
Expand Down
6 changes: 5 additions & 1 deletion Advanced/XmlBinding/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ Since tags for XML bindings are just a cache replacing a single tag will actuall

### Non bound content control

Content controls can be used without binding with XML in which case they will behave just as any other tag.
Content controls can be used without binding with XML in which case they will behave just as any other tag.

### Bound lists

Some Content controls such as Dropdown lists and ComboBoxes support element binding, which allows for easy elements population.
Binary file modified Advanced/XmlBinding/result.docx
Binary file not shown.
12 changes: 11 additions & 1 deletion Advanced/XmlBinding/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ public static void Main(string[] args)
new Item { product = "Planets", code = "PLN", description = "Big balls", quantity = 123567, title = "Very much"},
new Item { product = "Stars", code = "STR", description = "Glowing things", quantity = 66554433, title = "Very many"}
});
doc.Process(new
{
selectedValue = "Unknown",
dropdown = new[] {
new {name = "Option 1", value = "1"},
new {name = "Option 2", value = "2"},
new {name = "C value", value = "C"},
new {name = "Unknown", value = "unknown"}
}
});
}

//load resulting bound xml from the document
Expand All @@ -37,7 +47,7 @@ public static void Main(string[] args)
}
}

class Item
public class Item
{
public string product { get; set; }
public string code { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,49 @@

import java.awt.Desktop;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class XmlBindingExample {

private static String loadXml(File file) throws Exception {
ZipFile zip = new ZipFile(file);
ZipEntry entry = zip.getEntry("customXml/item1.xml");
InputStream is = zip.getInputStream(entry);
int size = (int) entry.getSize();
byte[] buffer = new byte[size];
int len;
int position = 0;
while ((len = is.read(buffer, position, size - position)) > 0) {
position += len;
}
is.close();
zip.close();
return new String(buffer, 0, buffer.length, "UTF-8");
}

public static void main(final String[] args) throws Exception {
InputStream templateStream = XmlBindingExample.class.getResourceAsStream("/Binding.docx");
File tmp = File.createTempFile("bind", ".docx");

FileOutputStream fos = new FileOutputStream(tmp);
ITemplateDocument tpl = Configuration.factory().open(templateStream, "docx", fos);
ITemplateDocument doc = Configuration.factory().open(templateStream, "docx", fos);

tpl.process(Arrays.asList(
doc.process(Arrays.asList(
new Item("Templater", "TPL", "Reporting library", 3, "How many"),
new Item("Computer", "COMP", "Hardware", 1, "Items"),
new Item("Planets", "PLN", "Big balls", 123567, "Very much"),
new Item("Stars", "STR", "Glowing things", 66554433, "Very many")));
doc.process(new Object() {
public final String selectedValue = "Unknown";
public final Dropdown[] dropdown = {
new Dropdown("Option 1", "1"),
new Dropdown("Option 2", "2"),
new Dropdown("C value", "C"),
new Dropdown("Unknown", "unknown")
};
});

tpl.close();
doc.close();
fos.close();

String xml = loadXml(tmp);

//put xml into document for presentation
tpl = Configuration.factory().open(tmp.getAbsolutePath());
tpl.templater().replace("xml", xml);
tpl.close();
doc = Configuration.factory().open(tmp.getAbsolutePath());
doc.templater().replace("xml", xml);
doc.close();

Desktop.getDesktop().open(tmp);
}

static class Item {
public static class Item {
public final String product;
public final String code;
public final String description;
Expand All @@ -68,4 +62,29 @@ public Item(String product, String code, String description, int quantity, Strin
this.title = title;
}
}

public static class Dropdown {
public String name;
public String value;
public Dropdown(String name, String value) {
this.name = name;
this.value = value;
}
}

private static String loadXml(File file) throws Exception {
ZipFile zip = new ZipFile(file);
ZipEntry entry = zip.getEntry("customXml/item1.xml");
InputStream is = zip.getInputStream(entry);
int size = (int) entry.getSize();
byte[] buffer = new byte[size];
int len;
int position = 0;
while ((len = is.read(buffer, position, size - position)) > 0) {
position += len;
}
is.close();
zip.close();
return new String(buffer, 0, buffer.length, StandardCharsets.UTF_8);
}
}
Binary file modified Advanced/XmlBinding/template/Binding.docx
Binary file not shown.
Loading

0 comments on commit 2bd7bac

Please sign in to comment.