Surendra Sharma

Surendra Sharma

Search This Blog

Tuesday, March 7, 2017

WFFM form is not visible in browser when serve from CD server



I am using Web Forms For Marketers 8.1 rev. 151217 which are dynamically rendering on web page which perfectly working fine on my local machine by using below code

@Html.Sitecore().Rendering("{F2CCA16D-7524-4E99-8EE0-78FF6394A3B3}", new { Datasource = "<id of the form item>", UniqueId = "<unique id of the form rendering>" })

After deploying on CD server and when viewed on browser at client side, my WFFM form and its fields are rendering in hidden state. I am saying hidden as form and its fields are rendering on page which I can identify from View Source my webpage on browser.

How to make WFFM forms and its fields rendering in visible state?

Solution :-

I able to resolve this by

  • Reinstalling WFFM CM package on server
  • Republishing all WFFM related items 
  • Clear the Sitecore Cache

I have also raise this question on Stack Overflow at http://sitecore.stackexchange.com/questions/4299/wffm-form-hidden-state-on-rendering and answer the same.


I hope this trick may be useful for you.

Thursday, February 23, 2017

Map WFFM Form fields with Word Mail Merge



In one of our requirement, we have to save WFFM form fields data in word document’s mail merge fields. This word document should be generated from mail merge template document.
 
I created WFFM form and created a new Save action under “/sitecore/system/Modules/Web Forms for Marketers/Settings/Actions/Save Actions” 

My WFFM form looks as

Sample WFFM Form
Sample WFFM Form


I bind the newly created Save action to this WFFM form.

I am using DocumentFormat.OpenXml to generate word document for mail merge fields.

Here is my word document template for mail merge fields

Word Mail Merge
Word Mail Merge


Below is code for this WFFM Save Action.

using System;
using System.Collections.Generic;
using System.Linq;
using Sitecore.Data;
using Sitecore.WFFM.Abstractions.Actions;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;

namespace SitecorePOCinMVC.Web
{
    public class MyCustomAction : ISaveAction
    {
        public ID ActionID { get; set; }
        public string UniqueKey { get; set; }
        public ActionType ActionType { get; private set; }
        public ActionState QueryState(ActionQueryContext queryContext)
        {
            return ActionState.Enabled;
        }

        public ActionCallContext Context { get; set; }

        public void Execute(ID formId, AdaptedResultList adaptedFields, ActionCallContext actionCallContext = null, params object[] data)
        {
            string companyName = adaptedFields.GetValueByFieldID("{083F0126-4912-4ED7-A4B4-D55869C73D67}");
            string companyID = adaptedFields.GetValueByFieldID("{5B128D2F-E671-4A07-BE7F-4BDE9385D4A9}");
            string entryDesc = adaptedFields.GetValueByFieldID("{C87FD86C-71A4-432F-8B78-9990F16F0477}");

            Dictionary<string, string> wffmFields = new Dictionary<string, string>();
            wffmFields.Add("Company Name", companyName);
            wffmFields.Add("Company ID", companyID);
            wffmFields.Add("Entry Desc", entryDesc);

            try
            {
                OpenXMLUtility.WFFMFieldsToMailMerge(wffmFields);
            }
            catch (Exception ex)
            {
                System.IO.File.AppendAllText("d:\\sitecoretext.txt", "PDF Error : -" + ex.Message);
            }
        }
    }

    class OpenXMLUtility
    {
        public static void WFFMFieldsToMailMerge(Dictionary<string, string> wffmFields)
        {

            string sourceFile = Path.Combine(@"D:\Sample Template.dotx");
            string destinationFile = Path.Combine(@"D:\" + DateTime.Now.ToString("ddMMyyyyhhmmss") + ".docx");

            // Don't continue if the template file name is not found
            if (!File.Exists(sourceFile))
            {
                throw new Exception(message: "TemplateFileName (" + sourceFile + ") does not exist");
            }

            // If the file is a DOTX file convert it to docx
            if (sourceFile.ToUpper().EndsWith("DOTX"))
            {
                RETURN_VAL resultValue = ConvertTemplate(sourceFile, destinationFile);

                if (!resultValue.Value)
                {
                    var result = resultValue;
                }
            }
            else
            {
                // Otherwise make a copy of the Word Document to the targetFileName
                File.Copy(sourceFile, destinationFile);
            }

            using (WordprocessingDocument doc = WordprocessingDocument.Open(destinationFile, true))
            {

                doc.ChangeDocumentType(WordprocessingDocumentType.Document);

                string FieldDelimeter = " MERGEFIELD ";

                var document = doc.MainDocumentPart.Document;

                foreach (var field in document.Descendants<FieldCode>())
                {
                    var fieldNameStart = field.Text.LastIndexOf(FieldDelimeter, System.StringComparison.Ordinal);
                    var fieldname = field.Text.Substring(fieldNameStart + FieldDelimeter.Length).Trim();

                    string newFieldName = field.Text.Replace(" MERGEFIELD  ", "").Replace("  \\* MERGEFORMAT ", "").Trim();

                    var splitChars = newFieldName.Split(new string[] { "\\b" }, StringSplitOptions.RemoveEmptyEntries);
                    var columnName = splitChars[0].Trim().Trim(new char[] { '"' });

                    if (splitChars.Length > 1)
                    {
                        var columnDesc = splitChars[1].Trim().Trim(new char[] { '"' });
                    }

                    // Go through all of the Run elements and replace the Text Elements Text Property
                    foreach (Run run in document.Descendants<Run>())
                    {
                        foreach (Text txtFromRun in run.Descendants<Text>().Where(a => a.Text.Contains("«" + columnName + "»")))
                        {
                            txtFromRun.Text = wffmFields[columnName];
                            break;
                        }
                    }
                }

                // If the Document has settings remove them so the end user doesn't get prompted to use the data source
                DocumentSettingsPart settingsPart = doc.MainDocumentPart.GetPartsOfType<DocumentSettingsPart>().First();

                var oxeSettings = settingsPart.Settings.Where(a => a.LocalName == "mailMerge").FirstOrDefault();

                if (oxeSettings != null)
                {
                    settingsPart.Settings.RemoveChild(oxeSettings);

                    settingsPart.Settings.Save();
                }

                doc.MainDocumentPart.Document.Save();

            }
        }

        // Struct to hold the return value and possible exception
        public struct RETURN_VAL
        {
            public bool Value;
            public string Exception;
        }

        /// <summary>
        /// Converts the DOTX to DOCX
        /// </summary>
        /// <returns>True or False (with an exception) if successful in converting the document</returns>
        private static RETURN_VAL ConvertTemplate(string _templateFileName, string _targetFileName)
        {
            try
            {
                MemoryStream msFile = null;

                using (Stream sTemplate = File.Open(_templateFileName, FileMode.Open, FileAccess.Read))
                {
                    msFile = new MemoryStream((int)sTemplate.Length);
                    sTemplate.CopyTo(msFile);
                    msFile.Position = 0L;
                }

                using (WordprocessingDocument wpdFile = WordprocessingDocument.Open(msFile, true))
                {
                    wpdFile.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);

                    MainDocumentPart docPart = wpdFile.MainDocumentPart;
                    docPart.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate", new System.Uri(_templateFileName, UriKind.RelativeOrAbsolute));

                    docPart.Document.Save();
                }

                // Flush the MemoryStream to the file
                File.WriteAllBytes(_targetFileName, msFile.ToArray());

                msFile.Close();

                return new RETURN_VAL { Value = true };
            }
            catch (Exception ex)
            {
                return new RETURN_VAL { Value = false, Exception = "DocumentGeneration::convertTemplate() - " + ex.ToString() };
            }
        }
    }
}

After executing this code, my WFFM fields values replace the word mail merge fields as

Sitecore WFFM with Word Mail Merge
Sitecore WFFM with Word Mail Merge


I hope you like this Sitecore tip. Stay tuned for more Sitecore related articles.

Till that happy Sitecoring :)

Please leave your comments or share this tip if it’s useful for you.