I have a button that exports a view to Excel from an Xpage. It works fairly well, but when the user opens up Excel there are no grid lines and I know they are going to freak out. I have looked for an hour on the internet for how to turn these one but I can't find how.
Does anyone know how to do this?
Here is my code"
var output:string = "";
for(i=0;i < sessionScope.searchDocIDArray.length; i++)
{
var docId=sessionScope.searchDocIDArray[i];
var doc=database.getDocumentByID(docId);
output += "<tr>";
output += "<td>" + doc.getItemValueString("user") + "</td>";
output += "<td>" + doc.getItemValueString("loc") + "</td>";
output += "<td>" + doc.getItemValueString("date") + "</td>";
output += "<td>" + doc.getItemValueString("workCategory") + "</td>";
output += "<td>" + doc.getItemValueString("state") + "</td>";
output += "<td>" + doc.getItemValueString("timeSpent") + "</td>";
output += "<td>" + doc.getItemValueString("notes") + "</td>";
output += "</tr>";
}
facesContext.getExternalContext().getResponse().setHeader("Content-disposition", "attachment; filename=TSC Time Spent.xlxs");
facesContext.getExternalContext().getResponse().setHeader("Cache-Control", "no-cache");
facesContext.getResponseWriter().write("<x:WorksheetOptions>")
facesContext.getResponseWriter().write("<x:Panes>");
facesContext.getResponseWriter().write("</x:Panes>");
facesContext.getResponseWriter().write("<x:WorksheetOptions>")
facesContext.getResponseWriter().write("<table><thead><tr><td><b>User</b></td><td><b>Loc</b></td><td><b>Date</b></td><td><b>Work Category</b></td><td><b>Time Spent</b></td><td><b>Notes</tr></thead>"+output+"</table>");
facesContext.getResponseWriter().endDocument();
One way to make sure grid lines are intact is to export to csv instead of using html tags to write out your content.
You also can assign css to your to td elements but the borders will not look like they do natively in excel.
Here is an example of using csv. This is a simplified version of something I used in afterRenderResponse:
var exCon = facesContext.getExternalContext();
var writer = facesContext.getResponseWriter();
var response = exCon.getResponse();
var output = "";
var colHeaders = "col1,col2,col3,col4,col5";
// Loop through data set
while (doc != null) {
output+="\"" + val1 + "\",";
output+="\"" + val2 + "\",";
output+="\"" + val3 + "\",";
output+="\"" + val4 + "\",";
output+="\"" + val5 + "\",";
output += #Char(13)+#Char(10); // start a new row
}
response.setContentType("application/csv-tab-delimited-table;charset=utf-8");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Disposition", "attachment;filename=actionExport.csv");
writer.write(colHeaders+#Char(13)+#Char(10)); // Add the first row as column titles and add line feed
writer.write(output+#Char(13)+#Char(10)); //
writer.endDocument();
It's going to take a bit more investigation, but I would recommend looking at using Apache POI for writing to Excel. It won't throw security alerts with Excel 2007+ like the table approach does. It has more specific APIs for setting styling. The HSSF classes are the ones you want (standing for Horrible SpreadSheet Format!).
Try adding this :-)
<x:WorksheetOptions>
<x:DisplayGridlines/>
</x:WorksheetOptions>
Related
I have notes documents that I would like to export to excel, depending on a date range.
No problem for the text fields , but how do I 'grab' the text out of a notes rtf to export it to excel.
I may not use POI 4 xpages , so I need another solution
To export the data to excel I use :
var exCon = facesContext.getExternalContext();
var writer = facesContext.getResponseWriter();
var response = exCon.getResponse();
output += "<tr>";
output += "<td>" + viewEnt.getColumnValues()[0]; + "</td>";
//etc for the other columns
response.setContentType("application/vnd.ms-excel");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Disposition","attachment; filename=export.xls");
writer.write("<table>");
writer.write("<thead><tr>");
writer.write("<td><b>First column name</b></td>");
//etc for the other columns
writer.write("</tr></thead>");
writer.write(output);
writer.write("</table>");
writer.endDocument();
That is working.
In column 8 I have the unid, so to get the rtf I tried :
var unid=viewEnt.getColumnValues()[8]
var doc:NotesDocument = database.getDocumentByUNID(unid);
var rtf = doc.getFirstItem("crm_doc").toString();
But this returns 'crm_doc' instead of the contents of crm_doc ....
toString converts the item to a String, not the content. Try getText instead.
I'm selecting documents in a view by daterange. The start date is alway correct but the end date isn't. The selection goes from the startdate till the last entry.
My code is :
var vDateRange = session.createDateRange(sessionScope.selectedStartDate, sessionScope.selectedEndDate);
var projects:NotesView = database.getView('visits_by_date_VB')
var viewNav:NotesViewNavigator = projects.createViewNav();
var viewEntryCollection:NotesViewEntryCollection = projects.getAllEntriesByKey(vDateRange);
var viewEnt:NotesViewEntry = viewEntryCollection.getFirstEntry();
var output:string = "";
while (viewEnt != null) {
output += "<tr>";
output += "<td>" + viewEnt.getColumnValues()[0]; + "</td>";
output += "<td>" + viewEnt.getColumnValues()[3] + "</td>";
output += "<td>" + viewEnt.getColumnValues()[4] + "</td>";
output += "<td>" + viewEnt.getColumnValues()[5] + "</td>";
output += "</tr>";
viewEnt = viewNav.getNext(viewEnt);
}
EDIT
Picking up dates with following code :
<xe:djDateTextBox id="StartDate"
defaultValue="#{javascript:sessionScope.selectedStartDate}"
value="#{sessionScope.selectedStartDate}">
<xp:this.converter>
<xp:convertDateTime type="date"
dateStyle="full">
</xp:convertDateTime>
</xp:this.converter>
</xe:djDateTextBox>
<xe:djDateTextBox id="EndDate"
defaultValue="#{javascript:sessionScope.selectedEndDate}"
value="#{sessionScope.selectedEndDate}">
<xp:this.converter>
<xp:convertDateTime type="date"
dateStyle="full">
</xp:convertDateTime>
</xp:this.converter>
</xe:djDateTextBox>
First column of the view is a date /time "style" sorted Ascending
The field on the form that stores the dates is a date time field .
Change this one line
viewEnt = viewNav.getNext(viewEnt);
to
viewEnt = viewEntryCollection.getNextEntry(viewEnt);
and it will work.
You initialize viewNav with the complete view content. That's why it starts with the right date from viewEntryCollection but runs always to view's end. You don't need the viewNav in this code and can delete this line.
I made an xpage element for ftsearch using a tutorial from IBM
My request: is there possible having 2 date fields ( as input requirements for the search ) to find those documents having the creation date inside the interval consisting of those 2 dates?
Should I create a computed field dtCreated where I will store the creation date and then in the search property of the view I should add something like this:
var tmpArray = new Array("");
var cTerms = 0;
if (sessionScope.searchDate1) && (sessionScope.searchDate2) {
tmpArray[cTerms++] = "(Field dtCreated > \"" + sessionScope.searhcDate1 + "\")" && "(Field dtCreated < \"" + sessionScope.searhcDate2 + "\")";
}
....
....
Or there is another alternative?
My 2 session variables are having Short (5/5/14) Date format. Also, my default value for those 2 dates (session variables) are "" but of course I add some values before clicking the Submit button.
Thanks for your time!
You can use the special field _creationDate as creation date (see answer from Tommy). Based on this the following example query will work in the Notes client:
Field _creationDate > 01-01-2014 AND Field _creationDate < 01-03-2014
In order to get this query to work with your specific code do this:
var tmpArray = new Array("");
var cTerms = 0;
var dateFormatter = new java.text.SimpleDateFormat( "dd-MM-yyyy" );
if (sessionScope.searchDate1) && (sessionScope.searchDate2) {
tmpArray[cTerms++] = "Field _creationDate > " + dateFormatter.format(sessionScope.searchDate1) + " AND Field _creationDate < " + dateFormatter.format(sessionScope.searchDate2);
}
If you want to do an FTSearch, _CreationDate can be used
Documentation (scroll to Searching for Header Information):
http://publib.boulder.ibm.com/infocenter/domhelp/v8r0/index.jsp?topic=%2Fcom.ibm.designer.domino.main.doc%2FH_CUSTOMIZING_SEARCH_FORMS_7304.html
E.g. (there might be typos):
tmpArray[cTerms++] = "(Field _creationDate>" + sessionScope.searhcDate1 + ") AND (Field _creationDate<" + sessionScope.searhcDate2 + ")";
Or my preferred syntax:
tmpArray[cTerms++] = "[_creationDate>" + sessionScope.searhcDate1 + "] AND [_creationDate<" + sessionScope.searhcDate2 + "]";
To build on Tommy's answer:
Specifically, try "yyyy/m/d" as the format. If those values in sessionScope are java.util.Date (the type that date fields use), you could try something like this (typing off the top of my head, not in an app, so my apologies for typos):
var tmpArray = [];
var cTerms = 0;
if(sessionScope.searchDate1 && sessionScope.searchDate2) {
var formatter = new java.text.SimpleDateFormat("yyyy/M/d");
tmpArray[cTerms++] = "[_CreationDate] >= " + formatter.format(sessionScope.searchDate1) + " and [_CreaationDate] <= " + formatter.format(sessionScope.searchDate2)
}
What you want to end up with is a FT query like:
[_CreationDate] >= 2014/1/1 and [_CreationDate] <= 2014/2/1
I am trying to populate a look-up column in a list, via the web service.
I am getting my data from an asp.net web form and using the web service method UpdateListItems and sending batch XML.
However, unless the user enters the exact data that the look up uses, the web service returns an error.
Is there anyway i can give the user of the web form, similar look-up functionality in order that the data passed will be identical?
i'm using share point 2007
The data source for the look-up column in share point is active directory.
_x0028_HR_x0029__x0020_Partner is the look up column, entering the users login name will look up their full name/ you can pick from a list.
Your help is much appreciated.
ClasService.Lists NewStarterList = new ClasService.Lists();
NewStarterList.Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["SPUserName"].ToString(),
ConfigurationManager.AppSettings["SPPassword"].ToString(), ConfigurationManager.AppSettings["SPDomain"].ToString());
NewStarterList.Url = ConfigurationManager.AppSettings["SPUrl"].ToString() + ConfigurationManager.AppSettings["SPServicePath"].ToString();
try
{
string strBatch = "<Method ID='1' Cmd='Update'>" +
"<Field Name='ID'>" + clasStarter.ClasID + "</Field>" +
"<Field Name='Title'>" + clasStarter.Name + "</Field>" +
"<Field Name='_x0028_HR_x0029__x0020_Job_x0020'>" + clasStarter.JobTitle + "</Field>" +
"<Field Name='Entity'>" + clasStarter.Entity + "</Field>" +
"<Field Name='Practice_x0020_Groups'>" + clasStarter.PracticeGroup + "</Field>" +
"<Field Name='Dept'>" + clasStarter.Department + "</Field>" +
"<Field Name='Physical_x0020_Desk_x0020_Locati'>" + clasStarter.Location + ", " + clasStarter.LocationInBuilding + ", " + clasStarter.Department + "</Field>" +
"<Field Name='_x0028_HR_x0029__x0020_Line_x002'>" + clasStarter.LineManager + "</Field>" +
"<Field Name='_x0028_HR_x0029__x0020_Buddy'>" + clasStarter.Buddy + "</Field>" +
"<Field Name='_x0028_HR_x0029__x0020_Partner'>" + clasStarter.Partner + "</Field>" +//is a look up
"</Method>";
XmlDocument xmlDoc = new System.Xml.XmlDocument();
System.Xml.XmlElement elBatch = xmlDoc.CreateElement("Batch");
elBatch.SetAttribute("OnError", "Continue");
elBatch.SetAttribute("ListVersion", "1");
elBatch.SetAttribute("ViewName", ConfigurationManager.AppSettings["SPViewID"].ToString());
elBatch.InnerXml = strBatch;
XmlNode ndReturn = NewStarterList.UpdateListItems(ConfigurationManager.AppSettings["SPListID"].ToString(), elBatch);
}
catch (Exception exp)
{
throw new Exception("NewStarterForm - Clas Update failed ", exp);
}
I haven't figured out a full solution my problem, but i have figured out part of it.
Share point look-up columns have two parts, an id and a value. If you don't know the value then you can just use -1;# as a substitute for the ID
an example of this is
"<Field Name='Partner'>-1;#" + partnerLogOnId + "</Field>"
I will probably use a list, that allows users of my form to select people, and will pass the partnerLogOnId to my web service method.
Pagination (Next button) doesn't work for custom BusinessDataListWebPart.
I am adding BusinessDataListWebPart using code. Everything works fine. I can see 20 data raw at the same time but when I click "Next Button", I can not see next 20-40 data. A postback occurs, but the pageindex never changes.
I am using following code to add BusinessDataListWebPart to the Sharepoint site.
BusinessDataListWebPart consumer = new BusinessDataListWebPart();
consumer.Title = title;
consumer.Application = instance.Name;
consumer.Entity = projEntity.Name;
consumer.XslLink = "/Style%20Library/XSL%20Style%20Sheets/" + xslFileName;
consumer.PageSize = 20;
OK..I found the answer.
For pagination I needed to add "ParameterBindings" to the business data list webpart.
My final code is, It works perfect.
BusinessDataListWebPart consumer = new BusinessDataListWebPart();
ServerContext serverContext = ServerContext.GetContext(site);
SqlSessionProvider.Instance().SetSharedResourceProviderToUse(serverContext);
LobSystemInstance instance = ApplicationRegistry.GetLobSystemInstanceByName(applicationName);
Entity projEntity = instance.GetEntities()[entityName];
consumer.Title = title;
consumer.Application = instance.Name;
consumer.Entity = projEntity.Name;
consumer.XslLink = "/Style%20Library/XSL%20Style%20Sheets/" + xslFileName;
consumer.PageSize = 20;
consumer.ParameterBindings = "<ParameterBinding Name=" + "\"dvt_firstrow\"" + " Location=" + "\"Postback;Connection\"" + "/>" +
" <ParameterBinding Name=" + "\"dvt_sortdir\"" + " Location=" + "\"Postback;Connection\"" + "/>" +
" <ParameterBinding Name=" + "\"dvt_sortfield\"" + " Location=" + "\"Postback;Connection\"" + "/>" +
" <ParameterBinding Name=" + "\"dvt_filterfields\"" + " Location=" + "\"Postback;Connection\"" + "/>" +
" <ParameterBinding Name=" + "\"dvt_partguid\"" + " Location=" + "\"Postback;Connection\"" + "/>";