Sorry if my question is not good because I am new to sharepoint.
I have some document in document library I like to other people can come to library and put their comment there.
with using InfoPath designer form and repeated section and publishing form to form library I can data entry in the fields of InfoPath and upload attachment and then submit to form library and then other users can come and put their comment in the form.
now my problem is, my files are in document library and all meta data there is in document library. now my question is if I want to put comments on each Document i have to make a form library and again data entry all meta data in InfoPath form and upload attachments,....and then publish.
it seems it is a duplicate job, I like to know what is the best practice in this case?
I like to know I have to start with form library from scratch?
i note i am using sharepoint server 2013 and InfoPath from.
I think I found my answer in the below link address:
[Uploading File Attachment Into a Folder in a SharePoint Document Library Using InfoPath Form][1]
, with uploading InfoPath attachments in separate document library my problem will be solved. because i wanted my files in the document library folders and also can use features of InfoPath form with using repeated section.
now at first i use InfoPath from in form library and attach required files and then after submitting, the attaches files will be upload in document library of sharepoint.
also I found in the book (infopath with sharepoint 2013 how to) appendix B:
Appendix B. Upload File Attachments in Forms to a Document
Library
This appendix presents a code-behind method that uploads an attached file to a separate document
library when the form is submitted. The code here was adapted from Pranab Paul’s blog on MSDN.
Form Scenario
The form used in this scenario contains a file attachment control with a field named fileAttach. There
is also a button to be used as a submit button with and ID of SubmitButton.
The user may upload a file to the form and then submit the form. There is a form library in SharePoint
to which to submit the InfoPath form instance, but there is also a document library in which the file
attached to the form needs to be uploaded. A data connection for submission has been created and
points to the form library.
The form contains code-behind and therefore must have Full Trust. It also must be published as an
Administrator-Approved form and then added to Form Services in SharePoint.
Submit Button and Code-Behind Setup
The custom submit button needs to have a rule added such that when the button is clicked the Submit
Data action is executed. Also, in the button properties you need to click Edit Code to produce the
button event handler and method in the code-behind:
Click here to view code image
public void InternalStartup()
{
((ButtonEvent)EventManager.ControlEvents["SubmitButton"]
).Clicked
+= new ClickedEventHandler(SubmitButton_Clicked);
}
public void SubmitButton_Clicked
(object sender, ClickedEventArgs e)
{
// Write your code here.
}
The code-behind project uses SharePoint functions and therefore needs a reference to the
Microsoft.SharePoint assembly. This is a similar requirement in the tracking changes solution
described in Chapter 17, “Track Changes in a Form,” so you may refer to those steps to include the
proper assembly reference in this file attachment solution.
Event Handler Code
Within the button event handler (SubmitButton_Clicked) you need code to perform the
retrieval of the attached file and the upload of that file to a document library. The code to perform this
is shown here:
Click here to view code image
public void SubmitButton_Clicked(object sender, ClickedEventArgs e)
{
XPathNavigator docXN = this.CreateNavigator();
XPathNavigator opnXN = docXN.SelectSingleNode("/my:myFields/my:fileAttach",
this.NamespaceManager);
byte[] attachmentNodeBytes = Convert.FromBase64String(opnXN.ToString());
// Position 20 contains a DWORD indicating the length of the
// filename buffer. The filename is stored as Unicode so the
// length is multiplied by 2.
int fnLength = attachmentNodeBytes[20] * 2;
byte[] fnBytes = new byte[fnLength];
// The actual filename starts at position 24...
for (int i = 0; i < fnBytes.Length; i++)
{
fnBytes[i] = attachmentNodeBytes[24 + i];
}
// Convert the filename bytes to a string. The string
// terminates with \0 so the actual filename is the
// original filename minus the last character !
char[] charFileName = System.Text.UnicodeEncoding.Unicode.GetChars(fnBytes);
string fileName = new string(charFileName);
fileName = fileName.Substring(0, fileName.Length - 1);
// The file is located after the header, which is 24 bytes long
// plus the length of the filename.
byte[] fileContents = new byte[attachmentNodeBytes.Length - (24 + fnLength)];
for (int i = 0; i < fileContents.Length; ++i)
{
fileContents[i] = attachmentNodeBytes[24 + fnLength + i];
}
string SiteURL = "http://SharePointRoot/DocumentLibrary/" + fileName;
SPWeb site = new SPSite(SiteURL).OpenWeb();
site.Files.Add(SiteURL, fileContents);
}
Deployment
As mentioned earlier, you need to publish the form as an Administrator-Approved form and then
upload the form template to Form Services in SharePoint. Once you upload it to Form Services, you
may use the form as the content type in the desired form library.
When a new form is instantiated and submitted, the form instance is saved in the form library you
specified in the data connection for submission, and the attached file is stored in the document library
you specified within the code-behind
Related
I have been working on legacy application where i am using Aspose.Words.jdk15.jar to print the .doc file. I have a requirement where i am getting list of value then we have to loop & print it in the doc file.
And that value we are replacing in doc using range.replace() method . This doc already exists in my workspace where we have mapped the value like this
Component Name:$COMPONENT_NAME
Billing Effective Date:$EFFECTIVE_DATE
Billing End Date:$END_DATE
and the code which i have written to replace the value of doc. So, my requirement is I need this value multiple times in my doc as per size of list.
for(int i=0;i<details.size();i++)
{
doc.getRange().replace("$COMPONENT_NAME" , checkNull(details.get(i).getComponentName()) + “,”, false, false);
doc.getRange().replace("$EFFECTIVE_DATE" , checkNull(details.get(i).getBillEffectiveDate()) + “,”, false, false);
doc.getRange().replace("$END_DATE" , checkNull(details.get(i).getBillEndDate()) + “,”, false, false);
}
The best way to achieve what you need is using mail Merge feature.
https://docs.aspose.com/words/java/about-mail-merge/
But in this case you need to replace your placeholders with mergefields in your template.
If you cannot change the template, you can clone the the document for each item in your list, replace values in the cloned document and them merge documents together to get the final result. Code will look like the following:
// Open template
Document doc = new Document("C:\\Temp\\in.doc");
// Create document where result will be stored to.
// Simply clone the original template without children,
// In this case styles of the original document will be kept.
Document result = (Document)doc.deepClone(false);
for(int i=0; i<details.length; i++)
{
Document component = doc.deepClone();
component.getRange().replace("$COMPONENT_NAME", details[i].getComponentName());
component.getRange().replace("$EFFECTIVE_DATE", details[i].getBillEffectiveDate().toString());
component.getRange().replace("$END_DATE", details[i].getBillEndDate().toString());
// Append the result to the final document.
result.appendDocument(component, ImportFormatMode.USE_DESTINATION_STYLES);
}
result.save("C:\\Temp\\out.doc");
But I would preferer Mail Merge approach.
I am trying to replace text on a specific page to upper case using Aspose.PDF for .Net. If anyone can provide any help that would be great. Thank you.
My name is Tilal Ahmad and I am a developer evangelist at Aspose.
You may use the documentation link for searching and replacing text on a specific page of the PDF document. You should call the Accept method for specific page index as suggested at the bottom of the documentation. Furthermore, for replacing text with uppercase you can use ToUpper() method of String object as follows.
....
textFragment.Text = textFragment.Text.ToUpper();
....
Edit: A sample code to change text case on a specific PDF page
//open document
Document pdfDocument = new Document(myDir + "testAspose.pdf");
//create TextAbsorber object to find all instances of the input search phrase
TextFragmentAbsorber textFragmentAbsorber = new TextFragmentAbsorber("");
//accept the absorber for all the pages
pdfDocument.Pages[2].Accept(textFragmentAbsorber);
//get the extracted text fragments
TextFragmentCollection textFragmentCollection = textFragmentAbsorber.TextFragments;
//loop through the fragments
foreach (TextFragment textFragment in textFragmentCollection)
{
//update text and other properties
textFragment.Text = textFragment.Text.ToUpper();
}
pdfDocument.Save(myDir+"replacetext_output.pdf");
I have a Web Form for Marketer set up done for one of my Pages.
I have Custom Submit Action written for it as shown below in the code snippet -
public class **CustomFormSubmit : ISaveAction**
{
public void Execute(ID formid, AdaptedResultList fields, params object[] data)
{
try
{
**//var returnValue= Custom Logic to save form data // returns true or false**
}
catch (Exception ex)
{
Logger.Log(ex.Message + ":" + builder, ExceptionCategory.Error);
throw;
}
}
In my above Web form - Success Mode is - SuccessMode/Redirect and I have a success Page configured for it.
My requirement in above scenario is to keep user on the same Page(with Form) if returnValue is false . (as shown in above code snippet)
Can anyone Please guide me in the above scenario as - how to keep user on the same Page with values filled in the form so that user can submit it again.
Product Details - 7.2 rev. 141226 , Web Forms for Marketers 2.4 rev.140117
To add further details -
I am not sure how can I go back to my page instead of the redirection in case if return is false in the above code snippet.
As soon the submit button is clicked the above function- Execute- gets called.
How do I go back to the Page - Do I need to override any function or customize something.
If any exception comes while saving data- then the control goes back to the same Page with all values filled by user retained -with the Save Action Failed Message which is configured in Sitecore .
So my requirement will be to go to to the form as happening in case of Exception when false comes as return value while saving data and to put customised Error Messages which might change each time, so not statically configured ,rather a dynamic one.
Thanks!
Saurabh
One option will be to redirect to the original page with the Form on.
Enable your form to populate the fields via Query String using the ReadQueryString property, via Presentation Details of the Form Renderer:
So on false of your Save Action you create a collection of query strings with the name of each Field, as it appears in the Form, followed by the User's value.
The code below will loop through all your fields and arrange them into a QueryString with its FieldName and Value;
string urlOfForm = HttpContext.Current.Request.Url.AbsolutePath;
var queryString = new StringBuilder("?");
foreach (AdaptedControlResult field in fields)
{
queryString.Append(string.Format("{0}={1}&", field.FieldName, field.Value));
}
urlOfForm = urlOfForm + queryString;
HttpContext.Current.Response.Redirect(urlOfForm);
Sitecore will then automatically populate the appropriate fields with the values, achieving your requirement.
EDIT
I have found that most Exceptions thrown will take the user back to the Form with their values populated. You can then pass in the cause of the failure to write to your CRM. See below for Example
if (submitFailed)
{
throw new Exception("The email address entered already exists in our System");
}
The complexity then comes in dynamically swapping out the Save Action Failed Message to show this Exception Message. All posts I find about custom Save Action Message state the only real approach is to redirect via your Custom Save Action to a different page showing a different message. Which is not suitable to your requirements.
I have found the pipeline Args you are going to need to patch FormSubmitFailedArgs and SubmitFailedArgs. The Former will need the following change
public FormSubmitFailedArgs(ID formID, AdaptedResultList fields, ID actionFailed, Exception ex)
: base(formID, actionFailed, ex)
{
this.Fields = fields;
this.ErrorMessage = ex.Message;
}
and the Latter will need
public SubmitFailedArgs(ID formID, ID actionFailed, string errorMessage, Exception innerException)
{
this.FormID = formID;
this.ActionFailed = actionFailed;
this.ErrorMessage = innerException.Message;
this.InnerException = innerException;
}
Location and Styling of Submit Message:
You need to find the FormRender sublayout file, this is defaulted to website\sitecore modules\Web\Web Forms for Marketers\Control\SitecoreSimpleFormAscx.ascx inside there you will find a compont called SubmitSummary this renders out the submit message so move it to where you require.
Also note it references the CssClass scfSubmitSummary this is what you will need to target to change the styling of the Message. This Answer is already REALLY long so I won't give a blow by blow how to change the styling of that class, see here for example - http://www.awareweb.com/awareblog/10-1-13-wffmguide
Pipeline Patching
I've dug in deeper, in order to use the custom Args we created for using the exception error message you will need to control the Pipeline which ultimately uses those Args, this is the processor Sitecore.Form.Core.Pipelines.FormSubmit.FormatMessage, Sitecore.Forms.Core in the <errorSubmit> Pipeline.
From my investigation it shouldn't take much effort then its a matter of patching it, you can modify if the Sitecore.Forms.config directly or use patch:instead from a config file within the App_Config/Includes folder - see here for more info.
One option would be to create a Custom Form Verification Action. You could save the data here, although it would be better to verify the data against your API here and then save the data in custom save action, simply since this seems more logical as to how WFFM was meant to function.
using Sitecore.Data;
using Sitecore.Form.Core.Controls.Data;
using Sitecore.Form.Core.Submit;
using System;
using System.Collections.Generic;
namespace Custom.WFFM
{
public class CustomVerificationStep : BaseCheckAction
{
public string FailedMessage { get; set; }
public override void Execute(ID formid, IEnumerable<ControlResult> fields)
{
// Call your API
// You have access to the fields, so you can pass them through as parameters to your if needed
bool flag = ServiceAPI.ValidateUserData(param1, param2, etc);
if (!flag)
{
throw new Exception(string.Format(this.FailedMessage ?? "There was an error while verifying the data against the service call"));
}
}
public override ActionState QueryState(ActionContext context)
{
return ActionState.DisabledSingleCall;
}
}
}
Create the corresponding Verification Action under /sitecore/system/Modules/Web Forms for Marketers/Settings/Actions/Form Verification:
You can change the error message by setting it in the Parameters field as <FailedMessage>Custom Failed Error Message</FailedMessage>.
And then add your verification step to your form:
If you need a different error message per form then you can set the error message to display from the Error Messages tab.
The user will then be returned to the same without any of the save actions being called and the form fields still filled in.
I know doc.Save() function save all page in one HTML file.
doc.RenderToScale() function save each page to the independent image file.
but i want read or save each page in independent HTML file,I had not idea,can you help me?
You can use the following code sample to convert each page to HTML or any other format supported by Aspose.Words.
String srcDoc = Common.DATA_DIR + "src.docx";
String dstDoc = Common.DATA_DIR + "dst {PAGE_NO}.html";
Document doc = new Document(srcDoc);
LayoutCollector layoutCollector = new LayoutCollector(doc);
// This will build layout model and collect necessary information.
doc.updatePageLayout();
// Split nodes in the document into separate pages.
DocumentPageSplitter splitter = new DocumentPageSplitter(layoutCollector);
// Save each page to disk as separate documents.
for (int page = 1; page <= doc.getPageCount(); page++)
{
Document pageDoc = splitter.getDocumentOfPage(page);
pageDoc.save(dstDoc.replace("{PAGE_NO}", page+""));
}
It depends on 3 other classes, which you can find in this zip file.
I work with Aspose as Developer Evangelist.
In the Workbox we have “Open” and “Preview” functionality.
Is it possible to modify the “Open” functionality to open the content editor item in a new browser tab, rather than displaying the “Content Editor” in a pop-up?
That's possible:
First, find out what code is used for the workbox. This can be done by opening the Workbox.xml (located in webroot/sitecore/shell/Applications/Workbox) file.
You'll see something like
<CodeBeside Type="Sitecore.Shell.Applications.Workbox.WorkboxForm,Sitecore.Client"/>
By using Reflector on the WorkboxForm class I can see that the following happens when you click 'Open' in workbox:
webControl["Click"] = string.Concat(new object[] { "Open(\"", item.ID, "\", \"", item.Language, "\", \"", item.Version, "\")" });
So you'll need to create your own version of a WorkboxForm, inheriting Sitecore's WorkboxForm class and override the Open method, something like so:
protected new void Open(string id, string language, string version)
{
// Your code goes here
}
In Workbox.xml, change the CodeBeside to point to your new class.
For more information on custom functionality in the Workbox, I can recommend reading through this article, which has a lot of detail in it, also on other methods in the Workbox.
There's also another useful question on StackOverflow already. The comment on the accepted answer points out you can put your Workbox.xml file into /sitecore/shell/override.
Please note that this is based on Sitecore 6.5 update 5, it might differ a bit in other versions.
In the Appconfig/Commands.config you can find commands and classes related to them.
I have reflected some commands like preview, open and understood what's going on internally.
e.g. name="item:open" type="Sitecore.Shell.Framework.Commands.ContentEditor.OpenItem,Sitecore.Kernel"
And I have overridded the "Open" mwthod in the workbox as follows to open the content editor item in the new tab,
...
UrlString urlString = new UrlString("/sitecore/shell/Applications/Content%20Editor");
urlString.Append("id", id);
urlString.Append("vs", version);
urlString.Append("ro", sectionId);
urlString.Append("la", language);
urlString.Append("fo", id);
SheerResponse.Eval("window.open('" + (object)urlString + "', '_blank')");
...
It works!!!!!