Aspose words API - mail merge functionality - can the "merged" text be richtext (with styles/images/bullets/tables)? - aspose

Looking for word api which can perform mail merge type of functionality with richtext. Basically, text will be richtext/formatted text with fonts styles and WILL have
a) images
b) bullets
c) tables
Overall purpose: Create a word template with bookmarks. Get get data from DB(for those fields) and insert. Data will be html text/richtext. Autogenerate word document. python or .net api will be preferred.
Can Aspose.words work with richtext as described above? Any other recommendations for excellent word APIs?

Yes, you can achieve this using Aspose.Words. You can use IFieldMergingCallback to insert formatted text upon mail merge. For example, see the following link
https://apireference.aspose.com/words/net/aspose.words.mailmerging/ifieldmergingcallback
In case of reach text (if you mean RTF or MarkDown formats) you first need to read this content into a separate instance of Document and then use DocumentBuilder.InsertDocument method
https://apireference.aspose.com/words/net/aspose.words/documentbuilder/methods/insertdocument
The following code example shows how to use InsertHtml method in IFieldMergingCallback
[Test]
public void Test001()
{
Document doc = new Document(#"C:\Temp\in.docx");
doc.MailMerge.FieldMergingCallback = new HandleMergeFieldInsertHtml();
const string html = #"<h1>Hello world!</h1>";
doc.MailMerge.Execute(new string[] { "myField" }, new object[] { html });
doc.Save(#"C:\Temp\out.docx");
}
private class HandleMergeFieldInsertHtml : IFieldMergingCallback
{
void IFieldMergingCallback.FieldMerging(FieldMergingArgs args)
{
FieldMergeField field = args.Field;
// Insert the text for this merge field as HTML data, using DocumentBuilder
DocumentBuilder builder = new DocumentBuilder(args.Document);
builder.MoveToMergeField(args.DocumentFieldName);
builder.Write(field.TextBefore ?? "");
builder.InsertHtml((string)args.FieldValue);
// The HTML text itself should not be inserted
// We have already inserted it as an HTML
args.Text = "";
}
void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs args)
{
// Do nothing
}
}
If you would like manually format the text, then you can use DocumentBuilder appropriate properties.
[Test]
public void Test001()
{
Document doc = new Document(#"C:\Temp\in.docx");
doc.MailMerge.FieldMergingCallback = new HandleMergeFieldInsertText();
const string text = #"Hello world!";
doc.MailMerge.Execute(new string[] { "myField" }, new object[] { text });
doc.Save(#"C:\Temp\out.docx");
}
private class HandleMergeFieldInsertText : IFieldMergingCallback
{
void IFieldMergingCallback.FieldMerging(FieldMergingArgs args)
{
FieldMergeField field = args.Field;
DocumentBuilder builder = new DocumentBuilder(args.Document);
builder.MoveToMergeField(args.DocumentFieldName);
// Apply style or other formatting.
builder.ParagraphFormat.StyleIdentifier = StyleIdentifier.Heading1;
builder.Write(field.TextBefore ?? "");
builder.Write((string)args.FieldValue);
// The text itself should not be inserted
// We have already inserted it using DocumentBuilder.
args.Text = "";
}
void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs args)
{
// Do nothing
}
}
Hope this helps.
Disclosure: I work at Aspose.Words team.

Related

Google Cloud TTS Voice selection

I just started to use the Google's TTS api, when I list the available voices api lists the names of the voices as
tr-TR-Standart-A
tr-TR-Standart-B
...
What should I write to the code below to select for example Standart-B voice?
texttospeech.types.VoiceSelectionParams(language_code='tr-TR')
Here's an example in C# - you need to specify both the language code and the name in the VoiceSelectionParams:
using Google.Cloud.TextToSpeech.V1;
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
var client = TextToSpeechClient.Create();
// List the voices, just for reference
foreach (var voice in client.ListVoices("tr-TR").Voices)
{
Console.WriteLine(voice.Name);
}
// Synthesize some speech
var input = new SynthesisInput { Text = "This is a demo of Google Cloud text to speech" };
// The language code is always required, even when it's sort of part of the name
var voiceSelection = new VoiceSelectionParams
{
LanguageCode = "tr-TR",
Name = "tr-TR-Standard-B"
};
var audioConfig = new AudioConfig { AudioEncoding = AudioEncoding.Mp3 };
var response = client.SynthesizeSpeech(input, voiceSelection, audioConfig);
File.WriteAllBytes("test.mp3", response.AudioContent.ToByteArray());
}
}
Judging by the documentation, I think in Python you'd want:
voice = texttospeech.types.VoiceSelectionParams(
language_code='tr-TR',
name='tr-TR-Standard-B')

How to display Highlighted text using Solrj

I am new to Solr and SolrJ. I am trying to use for a desktop application and I have files(text files) to index and search. I wanted to use highlight feature and display the fragments with highlight,but I don't get them to display in yellow background as you highlight a text, please let me know how to display the text in yellow background.
here is my code snippet:
public void TestHighLight(SolrQuery query) throws
SolrServerException, IOException {
query.setQuery("*");
query.set("hl", "true");
query.set("hl.snippets", "5");
query.set("q", "text:Pune");
query.set("hl.fl", "*");
QueryResponse queryResponse = client.query(query);
SolrDocumentList docs = queryResponse.getResults();
Iterator iter = docs.iterator();
for (int i = 0; i < docs.size(); i++) {
iter = docs.get(i).getFieldNames().iterator();
String fldVal = (String) docs.get(i).getFieldValue("id");
String docID = (String) docs.get(i).get("id");
while (iter.hasNext()) {
String highlighText = getHighlightedText(queryResponse,
"text", docID);
System.out.println(" tHighlightedText is " + highlighText );
}
}
}
The output looks like this:how do I color it ?
[ for Java Developer at Pune
Thanks a lot !
Set the pre and post parameters of the highlighter. Specifies the “tag” to use before a highlighted term. This can be any string, but is most often an HTML or XML tag.
e.g:
solrQueryHandler.setHighlightSimplePre("<font color="yellow">");
solrQueryHandler.setHighlightSimplePost("/font");
But note that this will work only for the Original Highlighter

Sitecore FileUtil.ZipFiles creating empty zip file

I am trying to use the ZipFiles() utility method and its producing an empty zip file. I am using Sitecore 6.5. There are no error, permissions or otherwise.
Any thoughts? Here is the code.
public void CreateZipFile(string zipfileName, List<string> files)
{
var zipfile = string.Format("{0}/{1}/{2}", TempFolder.Folder, "myfolder", zipfileName) ;
var fileArray = files.ToArray();
var x = FileUtil.ZipFiles(zipfile, fileArray);
}
EDIT:
I am passing the files like this
var files = new List<string> { FileUtil.MapPath("/temp/sample.xlf") };
The proper usage of FileUtil.ZipFiles method is:
FileUtil.ZipFiles("/test.zip", new []{"/web.config", "/otherfile.txt"})
Sitecore automatically maps paths. The zip file will be created in your web app root.
EDIT AFTER COMMENT
If you want to create a zip file outside the web root and with a flat structure inside, you can use Sitecore ZipWriter class like this:
public static string ZipFiles(string absolutePathToZipfile, string[] files)
{
using (ZipWriter zipWriter = new ZipWriter(absolutePathToZipfile))
{
foreach (string path in files)
{
using (FileStream fileStream = System.IO.File.OpenRead(path.StartsWith("/") ? FileUtil.MapPath(path) : path))
zipWriter.AddEntry(FileUtil.GetFileName(path), fileStream);
}
}
return absolutePathToZipfile;
}

Customise Sitecore RichTextEditor to add default wrapper

The front end (html and css) is set up such a way that for the description text from a Sitecore content field needs to have a <p> tag wrapped around it.
So by default the RTE wraps texts in a <p> tag = TRUE. BUT the catch is you will need to hit Enter or copy/paste multiple paragraphs.
How can we force Sitecore to add a P tag if it's just one line?
Fortunately, From the dll, one particular function caught my eye:
protected virtual void SetupScripts()
{
foreach (XmlNode node in Factory.GetConfigNodes("clientscripts/htmleditor/script"))
this.Result.Scripts.AppendFormat("<script src=\"{0}\" language=\"{1}\"></script>\n", (object) XmlUtil.GetAttribute("src", node), (object) XmlUtil.GetAttribute("language", node));
}
NICE, eh? The developers of SITECORE are clever after all.
So I did this in the web.config,
<!— CLIENT SCRIPTS
These script files are included in the client, e.g. '<script src="/myscript.js" language="JavaScript"/>'
—>
<clientscripts>
<everypage />
<htmleditor>
<script src=”/assets/js/CustomRTE.js” language=”javascript”/>
</htmleditor>
</clientscripts>
And overrode scSendRequest function from EditorWindow.aspx.
window.scSendRequest = function(evt, command) {
var editor = scRichText.getEditor();
if (editor.get_mode() == 2) { //If in HTML edit mode
editor.set_mode(1); //Set mode to Design
}
var htmls = editor.get_html(true);
var regex = /<p[^>]*>.*?<\/p>/i;
var match = regex.exec(htmls);
if(match == null && htmls != null) {
htmls = "<p>" + htmls + "</p>";
}
//$("EditorValue").value = editor.get_html(true);
$("EditorValue").value = htmls;
scForm.browser.clearEvent(evt);
scForm.postRequest("", "", "", command);
return false;
}
AND YAY .. double rainbow and unicorn.
You could create your own custom solution for this requirement as well.
You could create a new pipeline event in the
<saveRichTextContent> pipeline - This could enable you to append the tag when you hit save on the rich text editor in sitecore
<renderField> pipeline - This could on the fly wrap your text into <p></p> tags while rendering the page, if the tag was not there in the original rtf text.
If you go for method 1: <saveRichTextContent>
You could add to the pipeline in web.config:
<processor type="Sitecore72.Classes.WrapRichTextInParagraphOnSave, Sitecore72" />
And you could use the following corresponding code:
namespace Sitecore72.Classes
{
public class WrapRichTextInParagraphOnSave
{
public void Process(SaveRichTextContentArgs args)
{
if (!(args.Content.Trim().StartsWith("<p>") && args.Content.Trim().EndsWith("</p>")))
args.Content = "<p>" + args.Content + "</p>";
}
}
}
Please note, that this pipeline gets triggered only when you use the Show Editor buttong of a rich text field:
If you go for method 2: <renderField>
To append to this pipeline you would use this config:
<processor type="Sitecore72.Classes.WrapRichTextInParagraphOnRender, Sitecore72" />
And you could use the following corresponding code:
namespace Sitecore72.Classes
{
public class WrapRichTextInParagraphOnRender
{
public void Process(RenderFieldArgs args)
{
if (args.FieldTypeKey == "rich text" && !(args.Result.FirstPart.Trim().StartsWith("<p>") && args.Result.FirstPart.Trim().EndsWith("</p>")))
args.Result.FirstPart = "<p>" + args.Result.FirstPart + "</p>";
}
}
}
For both these, ensure you add reference to Sitecore.Kernel.dll and HtmlAgilityPack.dll. Both of these are available with the sitecore package solution.

How to get the large picture from feed with graph api?

When loading the Facebook feeds from one page, if a picture exist in the feed, I want to display the large picture.
How can I get with the graph API ? The picture link in the feed is not the large one.
Thanks.
The Graph API photo object has a picture connection (similar to that the user object has):
“The album-sized view of the photo. […] Returns: HTTP 302 redirect to the URL of the picture.”
So requesting https://graph.facebook.com/{object-id-from-feed}/picture will redirect you to the album-sized version of the photo immediately. (Usefull not only for displaying it in a browser, but also if f.e. you want to download the image to your server, using cURL with follow_redirect option set.)
Edit:
Beginning with API v2.3, the /picture edge for feed posts is deprecated.
However, as a field the picture can still be requested – but it will be a small one.
But full_picture is available as well.
So /{object-id-from-feed}?fields=picture,full_picture can be used to request those, or they can be requested directly with the rest of feed data, like this /page-id/feed?fields=picture,full_picture,… (additional fields, such as message etc., must be specified the same way.)
What worked for me :
getting the picture link from the feed and replacing "_s.jpg" with "_n.jpg"
OK, I found a better way. When you retrieve a feed with the graph API, any feed item with a type of photo will have a field called object_id, which is not there for plain status type items. Query the Graph API with that ID, e.g. https://graph.facebook.com/1234567890. Note that the object ID isn't an underscore-separated value like the main ID of that feed item is.
The result of the object_id query will be a new JSON dictionary, where you will have a source attribute containing a URL for an image that has so far been big enough for my needs.
There is additionally an images array that contains more image URLs for different sizes of the image, but the sizes there don't seem to be predictable, and don't all actually correspond to the physical dimensions of the image behind that URL.
I still wish there was a way to do this with a single Graph API call, but it doesn't look like there is one.
For high res image links from:
Link posts
Video posts
Photo posts
I use the following:
Note: The reason I give the _s -> _o hack precedence over the object_id/picture approach is because the object_id approach was not returning results for all images.
var picture = result.picture;
if (picture) {
if (result.type === 'photo') {
if (picture.indexOf('_s') !== -1) {
console.log('CONVERTING');
picture = picture.replace(/_s/, '_o');
} else if (result.object_id) {
picture = 'https://graph.facebook.com/' + result.object_id + '/picture?width=9999&height=9999';
}
} else {
var qps = result.picture.split('&');
for (var i = 0; i < qps.length; i++) {
var qp = qps[i];
var matches = qp.match(/(url=|src=)/gi);
if (matches && matches.length > 0) picture = decodeURIComponent(qp.split(matches[0])[1]);
}
}
}
This is a new method to get a big image. it was born after the previews method doesn't works
/**
* return a big url of facebook
* works onky for type PHOTO
* #param picture
* #param is a post type link
* #return url of image
*/
#Transactional
public String getBigImageByFacebookPicture(String pictrue,Boolean link){
if(link && pictrue.contains("url=http")){
String url = pictrue.substring(pictrue.indexOf("url=") + 4);
try {
url = java.net.URLDecoder.decode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
StringBuffer sb = new StringBuffer("Big image for Facebook link not found: ");
sb.append(link);
loggerTakePost.error(sb.toString());
return null;
}
return url;
}else{
try {
Document doc = Jsoup.connect(pictrue).get();
return doc.select("#fbPhotoImage").get(0).attr("src");
} catch (Exception e) {
StringBuffer sb = new StringBuffer("Big image for Facebook link not found: ");
sb.append(link);
loggerTakePost.error(sb.toString());
return null;
}
}
}
Enjoy your large image :)
Actually, you need two different solutions to fully fix this.
1] https://graph.facebook.com/{object_id}/picture
This solution works fine for images and videos posted to Facebook, but sadly, it returns small images in case the original image file was not uploaded to Facebook directly. (When posting a link to another site on your page for example).
2] The Facebook Graph API provides a way to get the full images in the feed itself for those external links. If you add 'full_picture' to the fields like in this example below when calling the API, you will be provided a link to the higher resolution version.
https://graph.facebook.com/your_facebook_id/posts?fields=id,link,full_picture,description,name&access_token=123456
Combining these two solutions I ended up filtering the input in PHP as follows:
if ( isset( $post['object_id'] ) ){
$image_url = 'https://graph.facebook.com/'.$post['object_id'].'/picture';
}else if ( isset( $post['full_picture'] ) ) {
$image_url = $post['full_picture'];
}else{
$image_url = '';
}
See: http://api-portal.anypoint.mulesoft.com/facebook/api/facebook-graph-api/docs/reference/pictures
Just put "?type=large" after the URL to get the big picture.
Thanks to #mattdlockyer for the JS solution. Here is a similar thing in PHP:
$posts = $facebook->api('/[page]/posts/', 'get');
foreach($posts['data'] as $post)
{
if(stristr(#$post['picture'], '_s.'))
{
$post['picture'] = str_replace('_s.', '_n.', #$post['picture']);
}
if(stristr(#$post['picture'], 'url='))
{
parse_str($post['picture'], $picturearr);
if($picturearr['url'])
$post['picture'] = $picturearr['url'];
}
//do more stuff with $post and $post['picture'] ...
}
After positive comment from #Lachezar Todorov I decided to post my current approach (including paging and using Json.NET ;):
try
{
FacebookClient fbClient = new FacebookClient(HttpContext.Current.Session[SessionFacebookAccessToken].ToString());
JObject posts = JObject.Parse(fbClient.Get(String.Format("/{0}/posts?fields=message,picture,link,attachments", FacebookPageId)).ToString());
JArray newsItems = (JArray)posts["data"];
List<NewsItem> result = new List<NewsItem>();
while (newsItems.Count > 0)
{
result.AddRange(GetItemsFromJsonData(newsItems));
if (result.Count > MaxNewsItems)
{
result.RemoveRange(MaxNewsItems, result.Count - MaxNewsItems);
break;
}
JToken paging = posts["paging"];
if (paging != null)
{
if (paging["next"] != null)
{
posts = JObject.Parse(fbClient.Get(paging.Value<String>("next")).ToString());
newsItems = (JArray)posts["data"];
}
}
}
return result;
}
And the helper method to retieve individual items:
private static IEnumerable<NewsItem> GetItemsFromJsonData(IEnumerable<JToken> items)
{
List<NewsItem> newsItems = new List<NewsItem>();
foreach (JToken item in items.Where(item => item["message"] != null))
{
NewsItem ni = new NewsItem
{
Message = item.Value<String>("message"),
DateTimeCreation = item.Value<DateTime?>("created_time"),
Link = item.Value<String>("link"),
Thumbnail = item.Value<String>("picture"),
// http://stackoverflow.com/questions/28319242/simplify-looking-up-nested-json-values-with-json-net/28359155#28359155
Image = (String)item.SelectToken("attachments.data[0].media.image.src") ?? (String)item.SelectToken("attachments.data[0].subattachments.data[0].media.image.src")
};
newsItems.Add(ni);
}
return newsItems;
}
NewsItem class I use:
public class NewsItem
{
public String Message { get; set; }
public DateTime? DateTimeCreation { get; set; }
public String Link { get; set; }
public String Thumbnail { get; set; }
public String Image { get; set; }
}