In FieldMergingCallback.FieldMerging and I set font to all Runs in Node =>
public void FieldMerging(FieldMergingArgs args)
{
if (args.FieldValue.ToString().Length > 100)
{
var node = args.Field.Start.ParentNode.ParentNode;
if (node is Shape)
{
var runlist = node.GetChildNodes(NodeType.Run, true);
foreach (Run run in runlist)
{
run.Font.Size = 6;
}
}
}
}
But in result pdf is:
Why is the font smaller than the third word?
Before performing mail merge, you can use the following code to apply same formatting to all Run nodes inside a merge field.
Document doc = new Document("D:\\temp\\input.docx");
foreach (Field field in doc.Range.Fields)
{
if (field.Type.Equals(Aspose.Words.Fields.FieldType.FieldMergeField))
{
Node currentNode = field.Start;
bool isContinue = true;
while (currentNode != null && isContinue)
{
if (currentNode.NodeType.Equals(NodeType.FieldEnd))
{
FieldEnd end = (FieldEnd)currentNode;
if (end == field.End)
isContinue = false;
}
if (currentNode.NodeType.Equals(NodeType.Run))
{
Run run = ((Run)currentNode);
run.Font.Size = 6;
}
Node nextNode = currentNode.NextPreOrder(currentNode.Document);
currentNode = nextNode;
}
}
}
doc.Save("D:\\Temp\\18.6.docx");
Hope, this helps. I work with Aspose as Developer Evangelist.
Related
I am trying to add nodes in a sorted manner to my linked list. My code just keeps adding to the end if the value is less than the end of the linked list. I am not sure how to fix this or if I am not fully checking for the right scenario.
I have tried to increment current until it is greater than the nodeToAdd to place the node between, but it always just places it at the end.
public void AddOrdered(int value)
{
LinkedListNode nodeToAdd = new LinkedListNode(value);
LinkedListNode cur = m_first;
if (m_first == null)
m_first = nodeToAdd;//new LinkedListNode(value);
else if (nodeToAdd.m_data < m_first.m_data)
{
AddAtFront(value);
}
else if (nodeToAdd.m_data < cur.m_next.m_data)
{
LinkedListNode temp = new LinkedListNode(value);
temp = m_first.m_next;
m_first.m_next = nodeToAdd;
nodeToAdd.m_next = temp;
}
else
{
AddAtEnd(value);
}
}
supplement add at end/front methods--which are working fine
public void AddAtEnd(int value)
{
LinkedListNode cur = m_first;
if (m_first == null)
{
LinkedListNode lnl = new LinkedListNode(value);
m_first = lnl;
}
while (cur.m_next != null)
{
cur = cur.m_next;
}
cur.m_next = new LinkedListNode(value);
}
public void AddAtFront(int value)
{
if (m_first == null)
{
LinkedListNode ln = new LinkedListNode(value);
m_first = ln;
}
else
{
LinkedListNode lnl = new LinkedListNode(value);
lnl.m_next = m_first;
m_first = lnl;
}
}
The values should get added in order but the output is placing them at the very end of the linked list unless new min/maxs are entered as values.
First I am assuming that m_first is your first node. With this as an assumption the code would be as follows:
public void AddOrdered(int value)
{
LinkedListNode nodeToAdd = new LinkedListNode(value);
LinkedListNode cur;
if (m_first == null || m_first.data >= nodeToAdd.data)
{
nodeToAdd.next = m_first;
m_first = nodeToAdd;
}
else
{
cur = m_first;
while (cur.next != null &&
cur.next.data < nodeToAdd.data)
cur = cur.next;
nodeToAdd.next = cur.next;
cur.next = nodeToAdd;
}
}
I have to convert word to html which I'm doing with Aspose and that is working well. The problem is that it is producing some redundant elements which I think is due to the way the text is store in word.
For example in my word document the text below appears:
AUTHORIZATION FOR RELEASE
When converted to html it becomes:
<span style="font-size:9pt">A</span>
<span style="font-size:9pt">UTHORIZATION FOR R</span>
<span style="font-size:9pt">ELEASE</span>
I'm using C# and would like a way to remove the redundant span elements. I'm thinking either AngleSharp or html-agility-pack should be able to do this but I'm not sure this is the best way?
What I wound up doing is iterating over all the elements and when adjacent span elements were detected I concatenated the text together. Here is some code if others run into this issue. Note code could use some cleanup.
static void CombineRedundantSpans(IElement parent)
{
if (parent != null)
{
if (parent.Children.Length > 1)
{
var children = parent.Children.ToArray();
var previousSibling = children[0];
for (int i = 1; i < children.Length; i++)
{
var current = children[i];
if (previousSibling is IHtmlSpanElement && current is IHtmlSpanElement)
{
if (IsSpanMatch((IHtmlSpanElement)previousSibling, (IHtmlSpanElement)current))
{
previousSibling.TextContent = previousSibling.TextContent + current.TextContent;
current.Remove();
}
else
previousSibling = current;
}
else
previousSibling = current;
}
}
foreach(var child in parent.Children)
{
CombineRedundantSpans(child);
}
}
}
static bool IsSpanMatch(IHtmlSpanElement first, IHtmlSpanElement second)
{
if (first.ChildElementCount < 2 && first.Attributes.Length == second.Attributes.Length)
{
foreach (var a in first.Attributes)
{
if (second.Attributes.Count(t => t.Equals(a)) == 0)
{
return false;
}
}
return true;
}
return false;
}
I have a bit of a pickle. There are a list of images I want to grab on a website. I know how to do that much, but I have to filter out the location of the images.
Such as I'd want to grab the images in a div tag with an id "theseImages", but there are another set of images within another div tag with an id called "notTheseImages". Looping through every tag into ah HtmlElementCollection with the tag "img" would ignore the divs, because it'd also grab the images from "notTheseImages."
Is there a way I could loop through the images while doing a check to see where those images are located in the div tags?
This could help you to do the selection of your current HTML and maybe for future occassions :)
protected HtmlElement[] GetElementsByParent(HtmlDocument document, HtmlElement baseElement = null, params string[] singleSelectors)
{
if (singleSelectors == null || singleSelectors.Length == 0)
{
throw new Exception("Please give at least 1 selector!");
}
IList<HtmlElement> result = new List<HtmlElement>();
bool last = singleSelectors.Length == 1;
string singleSelector = singleSelectors[0];
if (string.IsNullOrWhiteSpace(singleSelector) || string.IsNullOrWhiteSpace(singleSelector.Trim()))
{
return null;
}
singleSelector = singleSelector.Trim();
if (singleSelector.StartsWith("#"))
{
var item = document.GetElementById(singleSelector.Substring(1));
if (item == null)
{
return null;
}
if (last)
{
result.Add(item);
}
else
{
var results = GetElementsByParent(document, item, singleSelectors.Skip(1).ToArray());
if (results != null && results.Length > 0)
{
foreach (var res in results)
{
result.Add(res);
}
}
}
}
else if (singleSelector.StartsWith("."))
{
if (baseElement == null)
{
baseElement = document.Body;
}
foreach (HtmlElement child in baseElement.Children)
{
string cls;
if (!string.IsNullOrWhiteSpace((cls = child.GetAttribute("class"))))
{
if (cls.Split(' ').Contains(singleSelector.Substring(1)))
{
if (last)
{
result.Add(child);
}
else
{
var results = GetElementsByParent(document, child, singleSelectors.Skip(1).ToArray());
if (results != null && results.Length > 0)
{
foreach (var res in results)
{
result.Add(res);
}
}
}
}
}
}
}
else
{
HtmlElementCollection elements = null;
if (baseElement != null)
{
elements = baseElement.GetElementsByTagName(singleSelector);
}
else
{
elements = document.GetElementsByTagName(singleSelector);
}
foreach (HtmlElement item in elements)
{
if (last)
{
result.Add(item);
}
else
{
var results = GetElementsByParent(document, item, singleSelectors.Skip(1).ToArray());
if (results != null && results.Length > 0)
{
foreach (var res in results)
{
result.Add(res);
}
}
}
}
}
return result.ToArray();
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// here we can query
var result = GetElementsByParent(webBrowser1.Document, null, "#theseImages", "img");
}
result would then contain the images that are under #theseImages
Mind you the GetElementsByParent is fairly untested, I just tested it for your use case and it seemed to be ok.
Don't forget to only start the query once you are sure the document is completed ;)
I wrote the following code to iterate my Treeview and find the full path given.
I get the correct position and the listview also shows the correct content, but the treeview is not expanded. It seems that the .Expand() method does not firing.
What could that be about?
The Form with the Treeview is a Dialog, which is initialized once at the program-start and then is refreshed and shown when needed.
Because of the huge number of folders into the deep, I just load 2 levels of folders downward with each manually expanded.
Before I show the Dialog again, I set the SelectedPath to the full path which should be expanded and than calling the ExpandToPath method.
private void treeView1_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e) {
if(e.Node.Tag != null && e.Node.Nodes.Count > 0)
PopulateTreeView(e.Node, 1);
}
private void PopulateTreeView(TreeNode node, int depth) {
if(node.Tag != null) {
TreeViewTag tag = node.Tag as TreeViewTag;
if(tag.Visited && node.Nodes.Count > 0) {
foreach(TreeNode n in node.Nodes) {
if(depth <= 1)
PopulateTreeView(n, depth + 1);
}
} else {
TreeNode aNode;
try {
DirectoryInfo[] infos = tag.Info.GetDirectories();
foreach(DirectoryInfo subDir in infos) {
try {
aNode = new TreeNode(subDir.Name, 0, 0);
aNode.Tag = new TreeViewTag() { Info = subDir, Visited = true };
aNode.ImageKey = "folderOpen";
if(depth <= 1)
PopulateTreeView(aNode, depth + 1);
node.Nodes.Add(aNode);
} catch(UnauthorizedAccessException ex11) {
} catch(Exception ex12) {
}
}
} catch(UnauthorizedAccessException ex1) {
} catch(Exception ex2) {
}
}
}
}
public void ExpandToPath(string path) {
currentNodeInfo = new DirectoryInfo(path);
TreeNode root = this.treeView1.Nodes[0];
if(path.EndsWith(Path.DirectorySeparatorChar.ToString()))
path = path.Substring(0, path.Length - 1);
Stack<TreeNode> search = new Stack<TreeNode>();
search.Push(root);
while(search.Count > 0) {
TreeNode current = search.Pop();
string compare = (current.Tag as TreeViewTag).Info.FullName;
if(path.Equals(compare)) {
current.Expand();
PopulateListView((current.Tag as TreeViewTag).Info);
break;
} else {
if(path.StartsWith(compare)) {
current.Expand();
foreach(TreeNode node in current.Nodes) {
search.Push(node);
}
}
}
}
search.Clear();
search = null;
}
Im using Treeview control of System.Web.UI class, to display Category and subcategory of an item.
I have tried the following code but no hope
protected void tvwOrganisation_TreeNodeCheckChanged(object sender, TreeNodeEventArgs e)
{
if (tvwOrganisation.CheckedNodes.Count > 0)
{
// the selected nodes.
foreach (TreeNode node in tvwOrganisation.CheckedNodes)
{
if (node.ChildNodes.Count > 0)
{
foreach (TreeNode childNode in node.ChildNodes)
{
childNode.Checked = true;
}
}
}
}
}
Is there a way I can do this, I have tried javascript too.
Also what is the replace of AfterCheck - windows formd event in web forms.
The tree tag was as follows,
<asp:TreeView ID="tvwRegionCountry" runat="server" ShowCheckBoxes="All" ExpandDepth="0" AfterClientCheck="CheckChildNodes();" PopulateNodesFromClient="true" ShowLines="true" ShowExpandCollapse="true" OnTreeNodeCheckChanged="tvwRegionCountry_TreeNodeCheckChanged"
onclick="OnTreeClick(event)">
</asp:TreeView>
Added following JS as mentioned in asp.net treeview checkbox selection
<script language="javascript" type="text/javascript">
function OnTreeClick(evt) {
var src = window.event != window.undefined ? window.event.srcElement : evt.target;
var isChkBoxClick = (src.tagName.toLowerCase() == "input" && src.type == "checkbox");
if (isChkBoxClick) {
var parentTable = GetParentByTagName("table", src);
var nxtSibling = parentTable.nextSibling;
if (nxtSibling && nxtSibling.nodeType == 1)//check if nxt sibling is not null & is an element node
{
if (nxtSibling.tagName.toLowerCase() == "div") //if node has children
{
//check or uncheck children at all levels
CheckUncheckChildren(parentTable.nextSibling, src.checked);
}
}
//check or uncheck parents at all levels
CheckUncheckParents(src, src.checked);
}
}
function CheckUncheckChildren(childContainer, check) {
var childChkBoxes = childContainer.getElementsByTagName("input");
var childChkBoxCount = childChkBoxes.length;
for (var i = 0; i < childChkBoxCount; i++) {
childChkBoxes[i].checked = check;
}
}
function CheckUncheckParents(srcChild, check) {
var parentDiv = GetParentByTagName("div", srcChild);
var parentNodeTable = parentDiv.previousSibling;
if (parentNodeTable) {
var checkUncheckSwitch;
if (check) //checkbox checked
{
var isAllSiblingsChecked = AreAllSiblingsChecked(srcChild);
if (isAllSiblingsChecked)
checkUncheckSwitch = true;
else
return; //do not need to check parent if any(one or more) child not checked
}
else //checkbox unchecked
{
checkUncheckSwitch = false;
}
var inpElemsInParentTable = parentNodeTable.getElementsByTagName("input");
if (inpElemsInParentTable.length > 0) {
var parentNodeChkBox = inpElemsInParentTable[0];
parentNodeChkBox.checked = checkUncheckSwitch;
//do the same recursively
CheckUncheckParents(parentNodeChkBox, checkUncheckSwitch);
}
}
}
function AreAllSiblingsChecked(chkBox) {
var parentDiv = GetParentByTagName("div", chkBox);
var childCount = parentDiv.childNodes.length;
for (var i = 0; i < childCount; i++) {
if (parentDiv.childNodes[i].nodeType == 1) //check if the child node is an element node
{
if (parentDiv.childNodes[i].tagName.toLowerCase() == "table") {
var prevChkBox = parentDiv.childNodes[i].getElementsByTagName("input")[0];
//if any of sibling nodes are not checked, return false
if (!prevChkBox.checked) {
return false;
}
}
}
}
return true;
}
//utility function to get the container of an element by tagname
function GetParentByTagName(parentTagName, childElementObj) {
var parent = childElementObj.parentNode;
while (parent.tagName.toLowerCase() != parentTagName.toLowerCase()) {
parent = parent.parentNode;
}
return parent;
}
</script>
and it worked...