I'm trying to create an Excel spreadsheet from scratch using OpenXML and I've got everything working okay (dumping actual values into actual cells), but now I'm trying to apply number formatting to columns and I'm running into a problem. I have styles.xml that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<x:styleSheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:numFmts count="12">
<x:numFmt numFmtId="216" formatCode="#,###" />
<x:numFmt numFmtId="217" formatCode="$#,###" />
<x:numFmt numFmtId="218" formatCode="#0.00" />
<x:numFmt numFmtId="219" formatCode="#,###" />
<x:numFmt numFmtId="220" formatCode="#0.0%" />
<x:numFmt numFmtId="221" formatCode="#,###" />
<x:numFmt numFmtId="222" formatCode="#0.0%" />
<x:numFmt numFmtId="223" formatCode="#0.0%" />
<x:numFmt numFmtId="224" formatCode="#0.0%" />
<x:numFmt numFmtId="225" formatCode="#,###" />
<x:numFmt numFmtId="226" formatCode="#,###" />
<x:numFmt numFmtId="227" formatCode="#0.0%" />
</x:numFmts>
<x:cellXfs count="12">
<x:xf numFmtId="216" applyNumberFormat="1" />
<x:xf numFmtId="217" applyNumberFormat="1" />
<x:xf numFmtId="218" applyNumberFormat="1" />
<x:xf numFmtId="219" applyNumberFormat="1" />
<x:xf numFmtId="220" applyNumberFormat="1" />
<x:xf numFmtId="221" applyNumberFormat="1" />
<x:xf numFmtId="222" applyNumberFormat="1" />
<x:xf numFmtId="223" applyNumberFormat="1" />
<x:xf numFmtId="224" applyNumberFormat="1" />
<x:xf numFmtId="225" applyNumberFormat="1" />
<x:xf numFmtId="226" applyNumberFormat="1" />
<x:xf numFmtId="227" applyNumberFormat="1" />
</x:cellXfs>
</x:styleSheet>
But Excel doesn't seem to like it and removes it after "repairing" the file. What am I missing here? The docs are a little spotty on exactly what is needed to keep Excel happy.
I manually assigned the numFmtId starting at what I thought might be a suitably high number. Is that the right way to do it?
Also, I'm aware that the formatCode are duplicated, but I'd assumed Excel wouldn't get tripped up by that, I could consolidate them if necessary.
My column definitions look like this (in sheet.xml):
<x:cols>
<x:col min="1" max="1" width="7" />
<x:col min="2" max="2" width="58" />
<x:col min="3" max="3" width="16" style="0" />
<x:col min="4" max="4" width="6" style="1" />
<x:col min="5" max="5" width="17" style="2" />
<x:col min="6" max="6" width="16" style="3" />
<x:col min="7" max="7" width="18" style="4" />
<x:col min="8" max="8" width="17" style="5" />
<x:col min="9" max="9" width="20" style="6" />
<x:col min="10" max="10" width="21" style="7" />
<x:col min="11" max="11" width="21" style="8" />
<x:col min="12" max="12" width="16" style="9" />
<x:col min="13" max="13" width="16" style="10" />
<x:col min="14" max="14" width="19" style="11" />
</x:cols>
For comparison - here's a snippet from a working styles.xml file created by Excel itself:
<numFmts count="1">
<numFmt numFmtId="164" formatCode="#,##0\p"/> // where does 164 come from?
</numFmts>
<cellXfs count="3">
<xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/> // do you always need a 0 xf entry? It isn't referenced in the sheet.xml file
<xf numFmtId="3" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/> // assuming numFmtId = 3 is a built in format??
<xf numFmtId="164" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/>
</cellXfs>
Answering my own question, but I came across this post:
http://polymathprogrammer.com/2009/11/09/how-to-create-stylesheet-in-excel-open-xml/
Which suggested that the minimum stylesheet requires quite a few more things than just the numFmts and the cellXfs. So I adapted their code to produce a minimal stylesheet ready for me to insert my cell formats and number formats (which I was doing in a loop):
private Stylesheet CreateStylesheet()
{
Stylesheet ss = new Stylesheet();
Fonts fts = new Fonts();
DocumentFormat.OpenXml.Spreadsheet.Font ft = new DocumentFormat.OpenXml.Spreadsheet.Font()
{
FontName = new FontName()
{
Val = "Calibri"
},
FontSize = new FontSize()
{
Val = 11
}
};
fts.Append(ft);
fts.Count = (uint)fts.ChildElements.Count;
Fills fills = new Fills();
fills.Append(new Fill()
{
PatternFill = new PatternFill()
{
PatternType = PatternValues.None
}
});
fills.Append(new Fill()
{
PatternFill = new PatternFill()
{
PatternType = PatternValues.Gray125
}
});
fills.Count = (uint)fills.ChildElements.Count;
Borders borders = new Borders();
Border border = new Border()
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
};
borders.Append(border);
borders.Count = (uint)borders.ChildElements.Count;
CellStyleFormats csfs = new CellStyleFormats();
CellFormat cf = new CellFormat() {
NumberFormatId = 0,
FontId = 0,
FillId = 0,
BorderId = 0
};
csfs.Append(cf);
csfs.Count = (uint)csfs.ChildElements.Count;
NumberingFormats nfs = new NumberingFormats();
CellFormats cfs = new CellFormats();
cf = new CellFormat()
{
NumberFormatId = 0,
FontId = 0,
FillId = 0,
BorderId = 0,
FormatId = 0
};
cfs.Append(cf);
ss.Append(nfs);
ss.Append(fts);
ss.Append(fills);
ss.Append(borders);
ss.Append(csfs);
ss.Append(cfs);
CellStyles css = new CellStyles();
CellStyle cs = new CellStyle()
{
Name = "Normal",
FormatId = 0,
BuiltinId = 0
};
css.Append(cs);
css.Count = (uint)css.ChildElements.Count;
ss.Append(css);
DifferentialFormats dfs = new DifferentialFormats();
dfs.Count = 0;
ss.Append(dfs);
TableStyles tss = new TableStyles()
{
Count = 0,
DefaultTableStyle = "TableStyleMedium9",
DefaultPivotStyle = "PivotStyleLight16"
};
ss.Append(tss);
return ss;
}
Not positive that there aren't things there that could be dropped, but I don't have the patience to go through it by trial-and-error to see if it can be made any slimmer.
I guess a cell format must have a FontId, FillId, BorderId and FormatId in addition to the NumberFormatId and in order to have those ids, you need to create at least one entry for each of them. This is despite the XML Schema labeling them as "optional".
Related
In my camunda process i want use a timer catch event to wait a random duration between 5-15 seconds. Is it possible to assign this random duration to the event?
You can use a script task of type javascirpt to generate the value like:
"PT" + Math.floor(Math.random() * 11 +5) + "S";
and store it in a result process data. Subsequently reference the data in the time expression like:
#{timer}
Example Model:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions
xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0fr9mxs" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.1.0">
<bpmn:process id="ExampleprocessProcess" name="example-process" isExecutable="true">
<bpmn:endEvent id="EndEvent_0x6ir2l">
<bpmn:incoming>Flow_09qj0b7</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_09qj0b7" sourceRef="Event_18ugk9p" targetRef="EndEvent_0x6ir2l" />
<bpmn:intermediateCatchEvent id="Event_18ugk9p">
<bpmn:extensionElements />
<bpmn:incoming>SequenceFlow_16gzt2m</bpmn:incoming>
<bpmn:outgoing>Flow_09qj0b7</bpmn:outgoing>
<bpmn:timerEventDefinition id="TimerEventDefinition_0shqn5w">
<bpmn:timeDuration xsi:type="bpmn:tFormalExpression">#{timer}</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:intermediateCatchEvent>
<bpmn:scriptTask id="CreateRandomTimeTask" name="create random time" scriptFormat="javascript" camunda:resultVariable="timer">
<bpmn:extensionElements />
<bpmn:incoming>Flow_1x8rlyg</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_16gzt2m</bpmn:outgoing>
<bpmn:script>"PT" + Math.floor(Math.random() * 11 +5) + "S";</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="SequenceFlow_16gzt2m" sourceRef="CreateRandomTimeTask" targetRef="Event_18ugk9p" />
<bpmn:startEvent id="Event_0luae7f">
<bpmn:outgoing>Flow_1x8rlyg</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1x8rlyg" sourceRef="Event_0luae7f" targetRef="CreateRandomTimeTask" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="ExampleprocessProcess">
<bpmndi:BPMNEdge id="SequenceFlow_16gzt2m_di" bpmnElement="SequenceFlow_16gzt2m">
<di:waypoint x="370" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_09qj0b7_di" bpmnElement="Flow_09qj0b7">
<di:waypoint x="468" y="117" />
<di:waypoint x="522" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1x8rlyg_di" bpmnElement="Flow_1x8rlyg">
<di:waypoint x="188" y="117" />
<di:waypoint x="270" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_07yj7bl_di" bpmnElement="Event_18ugk9p">
<dc:Bounds x="432" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1ws8xyt_di" bpmnElement="CreateRandomTimeTask">
<dc:Bounds x="270" y="77" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0luae7f_di" bpmnElement="Event_0luae7f">
<dc:Bounds x="152" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_0x6ir2l_di" bpmnElement="EndEvent_0x6ir2l">
<dc:Bounds x="522" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Using Ext.NET combobox.
<ext:ComboBox runat="server"
ID="ComboBoxCategorizedList"
QueryMode="Local"
ValueField="Id"
EmptyText="Type to begin search..."
TypeAhead="false"
DisplayField="Name"
Width="500"
NoteAlign="Down" EnableKeyEvents="true"
Note="Press 'Search' icon or Press ENTER for more results"
RemoveClearTrigger="true">
<%--Note="Type '*' for a full list"--%>
<HtmlBin>
<ext:XScript runat="server">
<script type="text/javascript">
$(window).on("__refresh__", function () {
#{ StoreComboBoxCategorizedList }.reload();
});
</script>
</ext:XScript>
</HtmlBin>
<Store>
<ext:Store runat="server" ID="StoreComboBoxCategorizedList" OnReadData="ComboBoxCategorizedList_ReadData">
<Proxy>
<ext:PageProxy />
</Proxy>
<Model>
<ext:Model Id="ModelCategorizedComboBox" runat="server" IDProperty="Id">
<Fields>
<ext:ModelField Name="Id" />
<ext:ModelField Name="Name" />
<ext:ModelField Name="Type" />
<ext:ModelField Name="RefId" />
<ext:ModelField Name="Description" />
</Fields>
</ext:Model>
</Model>
<Listeners>
<Update Handler="#{ComboBoxCategorizedList}.expand();" />
<EndUpdate Handler="categorizedList();" />
</Listeners>
<Parameters>
<ext:StoreParameter Mode="Raw" Name="filter" Value="#{ComboBoxCategorizedList}.getValue()" />
</Parameters>
</ext:Store>
</Store>
<Triggers>
<ext:FieldTrigger Icon="Clear"/>
<ext:FieldTrigger Icon="Search"></ext:FieldTrigger>
</Triggers>
<Listeners>
<SpecialKey Fn="enterKeyPressHandler" />
<Expand Handler="categorizedList();" Delay="100" />
<BeforeSelect Fn="onBeforeSelect" />
<KeyPress Handler="#{ComboBoxCategorizedList}.getTrigger(1).onClick();" Buffer="1000" />
<Change Handler="filterComboxBoxFunction(#{StoreComboBoxCategorizedList}, #{ComboBoxCategorizedList}.getValue()); #{ComboBoxCategorizedList}.expand(); categorizedList();" Delay="100" />
</Listeners>
Not asking for debugging help, but I want to know if an Ext.NET or Extjs dev has a generic solution: Very simply ... I want to initiate a remote search only when the local search returns no records. So I am looking for the best way to wire this up to the combobox. I've looked at using the Expand event and BeforeQuery event but this seems to come up short.
I'm looking for best practices so i can add a "OnLocalQuery" event to my comboboxes; and then take action if the local query returns 0 matches.
I use this function and it works fine .. and without QueryMode="Local":
<ext:ComboBox ID="cmb_name" runat="server" FieldLabel="ComboBox" EmptyText="-Select-" HideTrigger="true" TriggerAction="All" SelectOnFocus="true" DisplayField="Name" ValueField="Id" Editable="true" TabIndex="11">
<Store>
<ext:Store ID="str_ComboBox" runat="server" PageSize="10">
<Model>
<ext:Model ID="mdl_ComboBox" runat="server">
<Fields>
<ext:ModelField Name="Id" />
<ext:ModelField Name="Name" />
<ext:ModelField Name="Type" />
<ext:ModelField Name="RefId" />
<ext:ModelField Name="Description" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<Listeners>
<Change Fn="fn_filter" />
</Listeners>
</ext:ComboBox>
<script type="text/javascript">
var fn_filter = function (_this, newValue, oldValue, eOpts) {
var n = 0;
if (_this.lastQuery == undefined || _this.lastQuery == null) {
_this.lastQuery = "";
}
_this.getStore().clearFilter(true);
_this.getStore().load();
_this.store.filter(function (item) {
if (item.get('Name').includes(_this.getRawValue())) {
n = n + 1;
return true;
}
else {
return false;
}
});
_this.expand();
if (n == 0) {
//returns no records
//enter code here Callback
}
}
</script>
i'm using XmlSlurper to get a value from an XML-Response. I copied the response to local String here for easier testing purposes. I need to get the value from jobReqId which is 506 in this case. If I use println: jobReqId.name(); i'm getting the correct node-name (jobReqId). If i'm using println jobReqId or println jobReqId.text(); i'm just getting empty String. Someone has an idea?
def body = """<JobApplicationAssessmentOrder>
<JobApplicationAssessmentOrder>
<jobApplication>
<JobApplication>
<applicationTemplateId>562</applicationTemplateId>
<lastModifiedDateTime>2020-05-28T11:43:47.000</lastModifiedDateTime>
<rating>-1</rating>
<source>1</source>
<agencyInfo />
<reference />
<usersSysId />
<cust_instr2 />
<cust_instr6 />
<cust_instr7 />
<timeToHire />
<currentEmployer />
<formerEmployee>false</formerEmployee>
<homePhone />
<phoneScreenDate />
<candComment />
<ownershpDate />
<firstName>Alex</firstName>
<lastModifiedByProxy />
<anonymizedDate />
<statusComments />
<applicationId>382</applicationId>
<candidateId>324</candidateId>
<dataSource>User Entered</dataSource>
<status>Open</status>
<lastName>K</lastName>
<candTypeWhenHired />
<hiredOn />
<phoneScreenDetails />
<sourceLabel>Corporate Site</sourceLabel>
<disabilityStatus />
<profileUpdated>0</profileUpdated>
<duplicateProfile>0</duplicateProfile>
<cust_SourceName />
<countryCode>DE</countryCode>
<averageRating>-1</averageRating>
<owner />
<jobReqId>506</jobReqId>
<contactEmail>alex#gmx.de</contactEmail>
<jobAppGuid />
<lastModifiedBy>USER</lastModifiedBy>
<nonApplicantStatus>Applied</nonApplicantStatus>
<resumeUploadDate />
<appStatusSetItemId>762</appStatusSetItemId>
<exportedOn />
<candConversionProcessed />
<referenceComments />
<anonymizedFlag>0</anonymizedFlag>
<referredBy />
<middleName />
<appLocale>de_DE</appLocale>
<cellPhone>2314</cellPhone>
<snapShotDate>2020-05-28T11:42:21.000</snapShotDate>
</JobApplication>
</jobApplication>
</JobApplicationAssessmentOrder>
</JobApplicationAssessmentOrder>"""
def xmlBody = new XmlSlurper().parseText(body);
def jobReqId = xmlBody.JobApplicationAssessmentOrder.JobApplicationAssessmentOrder.jobApplication.JobApplication.jobReqId;
println jobReqId
Your xmlBody is in the same position as the first JobApplicationAssessmentOrder node.
If you do this it works:
def jobReqId = xmlBody.JobApplicationAssessmentOrder.jobApplication.JobApplication.jobReqId
This is a common mistake, to prevent it, I always do it this way:
def JobApplicationAssessmentOrder = new XmlSlurper().parseText(body)
def jobReqId = JobApplicationAssessmentOrder.JobApplicationAssessmentOrder.jobApplication.JobApplication.jobReqId
I am new to use telerik controls. I want to bind data in dropdownlist that is in telerik RadGrid control. I have already been applied but it gives an error
Object reference not set to an instance of an object.
Here is my code given below :
Source code
<telerik:RadGrid runat="server" ID="RadGrid1" AutoGenerateColumns="false" AllowPaging="true"
OnNeedDataSource="RadGrid1_NeedDataSource" OnUpdateCommand="RadGrid1_UpdateCommand"
OnItemCreated="RadGrid1_ItemCreated" OnDeleteCommand="RadGrid1_DeleteCommand"
OnInsertCommand="RadGrid1_InsertCommand"
onitemdatabound="RadGrid1_ItemDataBound" >
<MasterTableView DataKeyNames="id" CommandItemDisplay="Top" InsertItemPageIndexAction="ShowItemOnCurrentPage">
<Columns>
<telerik:GridEditCommandColumn ButtonType="ImageButton" />
<telerik:GridBoundColumn DataField="id" HeaderText="ID" ReadOnly="true"
ForceExtractValue="Always" ConvertEmptyStringToNull="true" />
<telerik:GridTemplateColumn>
<ItemTemplate>
<asp:DropDownList ID="ddldept" DataTextField="name" DataValueField="id" runat="server"></asp:DropDownList>
</ItemTemplate>
</telerik:GridTemplateColumn>
<telerik:GridBoundColumn DataField="code" HeaderText="Branch Code" />
<telerik:GridBoundColumn DataField="name" HeaderText="Branch Name" />
<telerik:GridBoundColumn DataField="shortname" HeaderText="Branch Shorth Name" />
<telerik:GridBoundColumn DataField="hod" HeaderText="Head of Department"/>
<telerik:GridBoundColumn DataField="location" HeaderText="Location Address" />
<telerik:GridButtonColumn ConfirmText="Are you sure want to delete this Branch?" ConfirmDialogType="RadWindow"
ConfirmTitle="Delete" ButtonType="ImageButton" CommandName="Delete" />
</Columns>
<EditFormSettings>
<EditColumn ButtonType="ImageButton" />
</EditFormSettings>
</MasterTableView>
<PagerStyle Mode="NextPrevAndNumeric" />
<ClientSettings>
<ClientEvents OnRowDblClick="rowDblClick" />
</ClientSettings>
</telerik:RadGrid>
Main Code
protected void RadGrid1_ItemDataBound(object sender, GridItemEventArgs e)
{
DataTable dt=obj.display_branch();
GridEditableItem item = e.Item as GridEditableItem;
DropDownList list = item.FindControl("ddldept") as DropDownList;
list.DataSource = dt;
list.DataTextField = "name";
list.DataValueField = "id";
list.DataBind();
}
Try on RadGrid1_ItemCreated. That is how I achieved it.
Having a GridPane with 2 rows and 2 columns, setting the row constraints to 50 percent height results in unwanted behaviour.
Code:
<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="..." stylesheets="#general.css" prefWidth="800" prefHeight="600">
<top>
<VBox>
<!-- ... -->
</VBox>
</top>
<bottom>
<HBox>
<!-- ... -->
</HBox>
</bottom>
<center>
<GridPane >
<children>
<ScrollPane fx:id="tilePane" GridPane.columnIndex="0" GridPane.rowIndex="0">
<content>
</content>
<GridPane.margin>
<Insets bottom="2" left="2" right="2" top="2" />
</GridPane.margin>
</ScrollPane>
<TreeView fx:id="listPane" GridPane.columnIndex="0" GridPane.rowIndex="1">
<root>
<TreeItem value="Stages" />
</root>
<GridPane.margin>
<Insets bottom="2" left="2" right="2" top="2" />
</GridPane.margin>
</TreeView>
<ScrollPane fx:id="mapPane" GridPane.columnIndex="1" GridPane.rowIndex="0" GridPane.rowSpan="2">
<content>
</content>
<GridPane.margin>
<Insets bottom="2" left="2" right="2" top="2" />
</GridPane.margin>
</ScrollPane>
</children>
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" percentWidth="25"/>
<ColumnConstraints hgrow="ALWAYS" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="ALWAYS" percentHeight="50" />
<RowConstraints vgrow="ALWAYS" percentHeight="50" />
</rowConstraints>
</GridPane>
</center>
</BorderPane>
(mentioned attribute at the bottom)
I expected that the two rows would share their available height at a 50% rate. They do this, but they also consume a lot more space than needed.
Picture of the result with, and without percentHeight specified:
Do I understand percentHeight wrong, or is there another approach?