Quantcast
Channel: SoftArtisans
Viewing all 140 articles
Browse latest View live

Can ExcelWriter Handle Formulas with External References?

$
0
0

Problem

External references are references to a cell or range on a worksheet in another Excel workbook, or a reference to a defined name in another workbook.

ExcelWriter does not currently have the ability to parse formulas with external references. External references in formulas will cause ExcelWriter to throw an “Unable to parse formula: Error: Could not match input” error.

Solutions

Depending on how the formulas are being used, there are two workarounds to handle external references.

Solution 1: Avoid making API calls that would cause the formulas to be parsed

The ability to delay the parsing of formulas was added in ExcelWriter version 8.5.1.  Before this version, ExcelWriter parsed every formula in a worksheet automatically.  In 8.5.1 and later versions, formulas are only parsed if it is necessary. This means that as long as there are no calls in your code that would require ExcelWriter to parse the formulas, the formulas will be preserved. Calling CopySheet, or inserting or deleting sheets, columns, or rows will all cause ExcelWriter to parse the formulas.

Solution 2: Excel’s INDIRECT Function

If you need to set a formula programmatically or use methods that would cause ExcelWriter to parse the formulas with external references, Excel’s INDIRECT function can be used with the formula string passed as a parameter. For example:

wb.Worksheets[0].Cells[0,0].Formula = "+INDIRECT(\"'C:\\Temp\\[Book2.xlsx]Sheet1'!A1\")";

ExcelWriter will generate the correct ourput when the INDIRECT function is used. However, in order for the external reference in the formula to take effect, the source workbook needs to be open as well. If the source workbook is not open, the cell’s value will display “invalid cell reference error (#REF!)”


What to Do When OfficeWriter Sporadically Throws “General license key exception: Product key not installed.” Error

$
0
0

Problem

Even though the license key is in the registry, OfficeWriter sporadically throws the error “General license key exception: Product key not installed.” on Windows 2008 or above.

This scenario has been known to occur when using a custom identity on an application pool in IIS 7 or above, OfficeWriter sporadically throws the error “General license key exception: Product key not installed.”  The combination of several factors in IIS 7.5 and Windows 2008 can cause problems for application pools running under a custom identity if they need to read from the registry.

  1. Windows 2008 introduced application pool identities.
  2. Windows 2008 also added new functionality to the user profile in Windows 2008 that causes the OS to more aggressively clean up registry handles when they are not needed.
  3. Additionally, IIS 7 and above does not load the user profiles by default.

Note:  If you are receiving the  ”General license key exception: Product key not installed.” error consistently, it is likely that the license key is not installed properly. Instructions for installing OfficeWriter license keys can be found here.

Solution

The “Load user Profile” setting

In IIS 7 and above, there is an application pool setting called “load user profile.”  When this is set to true, IIS will load the user profile for the application pool identity. This will keep Windows from cleaning the registry handles necessary for OfficeWriter to read the license key.

To set “load user profile” to true:

  1. Open the IIS Management Console. This can be done by going to Run and typing in inetmgr
  2. Open the Application Pools window by clicking View Application Pools on the Actions pane, and select the Application Pool you want to configure.
  3. Right-click the Application Pool and select Advanced Settings…
  4. Under the Process Model menu, change Load User Profile to true.

Knowledge Base - IIS

Can I Print ExcelWriter Generated Files from the Server?

$
0
0

Problem

I am trying to print ExcelWriter generated files. What are my options?

Solution

ExcelWriter does not currently support printing directly from the server.  In order to print, the contents of the Excel file must first be rendered. As ExcelWriter does not currently have the ability to render content, rendering is handled by Excel when the output file is opened by the client. This means that in order to support printing directly from a web server it would be necessary to have Excel on the server. However, having Excel on a web server is not recommended.

There are two workarounds that we recommend to meet your printing needs:

  • Save files to a dedicated printing server
  • Automate printing using a VBA macro, when the file is opened on the client

The ability to render Excel files is being planned for a future release of ExcelWriter.

Setting Print Options

Before printing you can set all your print options programatically through ExcelApplication.      Example code is below:

	ExcelApplication xlApp = new ExcelApplication();
	Workbook wb = xlApp.Open(Page.MapPath("AutoPrint.xls"));
	Worksheet ws = wb.Worksheets[0];

	PageSetup ps = ws.PageSetup; // get the PageSetup object
	ps.PrintArea = ws.CreateArea("A1:J10"); // set the area to be printed

	// format center header as Arial, Bold and display the file name
	ps.CenterHeader = "&\"Arial,Bold\"&F";
	ps.RightHeader = "Printed at &T on &D"; // display time and date
	ps.CenterFooter = "&P of &N"; // display page numbers (“# of #”)

	// set the margins
	ps.LeftMargin = 0.75;
	ps.RightMargin = 0.75;
	ps.TopMargin = 1.0;
	ps.BottomMargin = 1.0;
	ps.HeaderMargin = 0.5;
	ps.FooterMargin = 0.5;

	ps.PrintComments = false; // don’t print comments
	ps.Orientation = PageSetup.PageOrientation.Landscape; // print in landscape
	ps.CenterHorizontally = true; // center print area horizontally
	ps.CenterVertically = true; // center print area vertically
	Dim xlApp As ExcelApplication = New ExcelApplication()
	Dim wb As Workbook = xlApp.Open(Page.MapPath("AutoPrint.xls"))
	Dim ws As Worksheet = wb.Worksheets(0)

	'set the PageSetup properties
	Dim ps As PageSetup = ws.PageSetup 'get the PageSetup object
	ps.PrintArea = ws.CreateArea("A1:J10") 'set the area to be printed

	'format center header as Arial, Bold and display the file name
	ps.CenterHeader = "&""Arial,Bold""&F" 
	ps.RightHeader = "Printed at &T on &D" 'display time and date information
	ps.CenterFooter = "&P of &N" 'display page numbers (“# of #”)

	'set the margins
	ps.LeftMargin = 0.75
	ps.RightMargin = 0.75
	ps.TopMargin = 1.0
	ps.BottomMargin = 1.0
	ps.HeaderMargin = 0.5
	ps.FooterMargin = 0.5

	ps.PrintComments = False 'don’t print comments
	ps.Orientation = PageSetup.PageOrientation.Landscape 'print in landscape
	ps.CenterHorizontally = True 'center print area horizontally
	ps.CenterVertically = True 'center print area vertically

	xlApp.Save(wb, Page.Response, "AutoPrint.xls", False)

Note: Print options do not need to be set programmatically.  Any print options set in an input file will be preserved by ExcelWriter.

Solution 1 – Save files to a dedicated printing server

One workaround that several of our customers have implemented, is to have a separate box with Excel on it that is exclusively for printing. The files on the web server that are selected for printing are saved into the specified directory on the printing server. This can be done using OfficeWriter code and the UNC path, as shown below.

//Save the current ExcelWriter object to a UNC path
myExcelApplicaton.Save(MyWorkbook, @"\\printingServer\printingDirectory\" + fileName);

You can write a simple process that will run on the printing server and automatically print, using Excel, any file that is dropped to a certain directory.

Solution 2 – automate printing using a VBA Macro, when the file is opened on client

Using a VBA macro, you can automate printing of a file when it is opened on the client. ExcelWriter preserves macros, so they can be included in the input file or template.

This method (automatically printing the spreadsheet when opened on the client) requires that you use a pre-existing Excel file, designed directly in Microsoft Excel. This pre-existing Excel file contains VBA code in the Workbook_Open() event that prints the active workbook:

'Method will run when the workbook is opened in Excel 
Private Sub Workbook_Open()
    ActiveWorkbook.PrintOut Copies:=1, Collate:=True
End Sub

Creating Dynamic Links With MergeFields in Microsoft Word

$
0
0

Introduction

MergeFields allow users to import dynamic content in Microsoft Word. While this feature is very useful in many situations, it can be unclear how you must handle MergeFields nested inside of fields like hyperlinks. A user might want to have both dynamic link test and destinations for their hyperlinks. Unfortunately, how to achieve this is unclear because Hyperlink field codes only take a destination parameter. There is no place to put a merge field for your dynamic display text. In this article, I will show how to create fully dynamic links for Microsoft Word 2007 and up!

Step 1: Adding a Hyperlink Field

  • Put your cursor where you want to place the hyperlink
  • Go to Insert->Hyperlink
  • In the dialog box:
    • Next to Text to Display, enter something like “Temp Display Text”
    • Next to Address, enter something like “Temp Link”

You Should Now Have Something Like This:

KB_Step1

Step 2: Adding a Dynamic Destination Location

  • Press ALT+F9 to see the field code.
  • Delete the “Temp Link” text inside of the quotes.
  • If you have a base url location, enter it in between the quotes. Then proceed to the next step.
  • Now we must add a MergeField to get dynamic urls.
    • Put your cursor before the closing quote of your destination location.
      • Go to Insert-> Quick Parts-> Field.
      • Select MergeField from the Field Names menu.
      • Add the Field Name to identify the MergeField.
      • Click “OK” to exit the dialog.

You Should Now Have Something Like This:

KB_Step2

Step 3: Adding a Dynamic Link Text

  • Press ALT+F9 to hide the field code.
  • Delete the “Temp Display Text”  except for the last character.
  • Now we need to insert a MergeField.
    • Go to Insert-> Quick Parts-> Field.
    • Select MergeField from the Field Names menu.
    • Add the Field Name to identify the MergeField.
    • Click “OK” to exit the dialog.
  • Delete the last character of the temporary text.
  • If you did it correctly, you will still see a link mouseover when you hover over the link text MergeField.

You Should Now Have Something Like This:

KB_Step3

Conclusion

Now when you bind your data with MailMerge or WordWriter, your links will contain dynamic link text and destinations! Thanks for reading!

How to Use the LineBreakstoParagraphs Property

$
0
0

The LineBreakstoParagraphs Property

A new feature in the WordWriter 8.6.1 WordTemplate Object is the ability to output new paragraphs where there are line breaks in your data using the LineBreakstoParagraphs property. This allows the user to have their text separate into new paragraphs every time there is a line break. The biggest benefit of this feature is that each new paragraph that is inserted will inherit the paragraph styles of its MergeField, including hanging paragraph settings, indentations after paragraphs, alignment, spacing, and orientation, to name a few. This means a single merge field can now output many identically formatted paragraphs rather than a single, large paragraph.

How to Use

By default, LineBreakstoParagraphs is set to False, and line breaks are inserted as soft breaks. A soft break is when text goes to the next line, but is still a part of the previous paragraph. Therefore the new line lacks any typical spacing and indentation that would occur between paragraphs. A soft return can be done in Word by pressing Shift + Enter. To use LineBreakstoParagraphs, you must set the property to true before calling Open(). Also be aware that this property only works on OOXML Word documents (.docx, .dotx, etc).

Comparison

LineBreakstoParagraphs Set to FALSE (DEFAULT)
 KB_LB1
LineBreakstoParagraphs Set to TRUE
KB_LB2

Sample Code

// Names of your mergefields
string[] NamesArr = { @"MultiLineString" };

//Your long multi-line string of text with linebreaks.
object[] ValuesArr = {  
@"Lorem ipsum .... 
Mauris ac elit ... 
Cras mi nisi....};

WordTemplate WordTempl = new WordTemplate();

//Set LineBreakstoParagraphs to true
WordTempl.LineBreaksToParagraphs = true;

WordTempl.Open(Page.MapPath("/LineBreakstoParaDemo.docx"));

//Set the datasource to the arrays.
WordTempl.SetDataSource(ValuesArr, NamesArr);
WordTempl.Process(); 
WordTempl.Save(Page.Response, "Demo.docx", false);

Excel Charts Don’t Follow “Move and Size with Cells” Option

$
0
0

Problem

Excel’s “Move and Size with Cells” option allows you to automatically re-size charts if the cells that contain the chart are added or re-sized.

With ExcelWriter, when the “Move and Size with Cells” option is selected in Excel, charts are not re-sized based on rows that are added from data being imported into data markers using the ExcelTemplate object (or OfficeWriter’s SSRS integration). Charts are re-sized if rows are added explicitly using Worksheet.InsertRow.

Example 

The pictures below show a file that has “Move and Size with Cells” option selected, before and after it has been processed by ExcelWriter.

Template

KB_ChartExample1

Incorrect output - Note that the chart remained the same size as before the data was imported.

ExcelWriter Chart

The correct output should look like the following:

ExcelWriter Chart

Solutions

Re-sizing Excel charts to match a data set can be done programmatically with ExcelApplication or with a VBA macro. Both solutions require a named range containing the data whose height you wish to match.

Create a named range

In order to determine which data to match the size of the charts to, we will need to create a named range in your template. In the example above, a named range, called “Chart_Range” was created in cell A5. ExcelWriter will automatically expand the named range to contain all of the data imported into the data marker. Named ranges can be accessed programmatically using ExcelWriter.

Solution 1 – Use ExcelApplication

The ExcelApplication API has all the functions necessary to re-size your chart. This method assumes that you have created a named range in your template and then populated the template with data using ExcelTemplate’s Process method. Once Process is called, the named range would will expand to match the size of the imported data. In order to re-size the charts we will use ExcelApplication to determine the height of the named range by getting the heights of all the rows in the range. Then we will set the height of the chart to match. The following steps will show you how:

1) Pass the processed Template to ExcelApplication

Once our template contains data, it can be passed to ExcelApplication to be formatted. This can be done with ExcelApplication.Open.

ExcelApplicaton xla = new ExcelApplication();
Workbook wb = xla.Open(xlTemplate);
//locate the correct worksheet
Worksheet ws = wb.Worksheets["ChartingExample"];

2) Get the Named Range

Now we must locate the named range we created earlier:

//Get the named range
Range chartData = wb.GetNamedRange("Chart_Range");

3) Get the Area with the populated cells from the Named Range

In order to determine the heights of the rows we create an Area object.  The Area can be obtained through the named range.

//Get the area
Area dataArea = chartData.Areas[0].PopulatedCells;

4) Get the height of the Area by looping through all the rows

Now we can determine how tall the area is by getting the heights of all the rows in the area. Row heights are returned in points.

//A variable to keep track of the heights
double rowHeights = 0;

//loop through the rows
for (int i = 0; i < area.RowCount; i++)
{
     rowHeights = rowHeights + dataArea.getRowHeight(i);
}

5) Access and re-size the chart

Next, we need to get a handle on our chart.  The call below gets the first chart in the worksheet.  Once we have the chart we can easily set the height of the chart in points.

//Create a Charts object
Charts charts = ws.Charts;
Chart chartToResize = ws.Charts[0];

//re-size the chart
chartToResize.Height = rowHeights;

Now when you save and open your workbook, you chart will have the same height as the data in the range.

Solution 2 – Use a VBA macro

Using a VBA macro in your Excel template spreadsheet you can automatically re-size the charts upon opening the file.  The msdn documentation contains more general information about creating macros.

Note: Excel files containing macros must be saved as .xlsm files and may not work with very high security settings.

The following steps will walk you through this process:

1) Write the macro

The macro below will re-size the first chart in the worksheet.

The code is located in the auto_open method so that it will be run when the file is opened.

Sub auto_open()
' Method to change the size of the chart based on size of data in column
    Dim r As Range
    Set r = Sheet1.Range("Chart_Range")

    'Changes the height of the first chart to match the range height
    Sheet1.ChartObjects(0).Height = r.Height + 50

End Sub

2) Save your template and process with ExcelWriter

Your output should now have the same height as the data in the range.

For more information about charts in ExcelWriter see our documentation on Charts in ExcelApplication.

Released in OfficeWriter 8.6.1 – IEnumerable Feature

$
0
0

In OfficeWriter 8.6.1, we added a new feature that may have been flying under your radar, and I wanted to let you in on the story of how it came about.

When I first arrived at SoftArtisans I went through training of our entire product line.  As I was reviewing the training material, I came across the ExcelWriter Template section. I saw how to add data markers to my spreadsheet, and it seemed intuitive, so I went ahead and tried it:

Image

At that moment, I was thinking “This is pretty slick. Now, I can just pass things into the spreadsheet!”  I’m not the greatest at reading documentation; I just like to learn by doing, so I opened Visual Studio and started writing code:


</div>
<div>

class Expense

</div>
<div>

{

</div>
<div>

double Amount { get; set; }

</div>
<div>

string Description = "";

</div>
<div>

bool Approved { get { return (Amount > 1000); } }

</div>
<div>

}

</div>
<div>

&nbsp;

</div>
<div>

for (int i=0; i<1000; i++)

</div>
<div>

expenses.Add(new Expense(i));

</div>
<div>

Looking good so far.  What I did next, however, was my downfall:


</div>
<div>

ExcelTemplate xlt = new ExcelTemplate();

</div>
<div>

xlt.BindData(expenses);

</div>
<div>

Woops! I received an error. I was looking for a way to enumerate using the OfficeWriter API. After some design discussions, late nights of coding, and extensive peer review I’m proud to say this is now a part of the API!

Now there are a few things you should know before you dive right in and start using it. I’ll start off with what we do support: 

  • The new API accepts an IEnumerable<T> in place of a DataTable, DataReader, or array.
  • Public properties and fields (both static and instance) are available for data markers.
  • Public properties and fields of base classes (again, for static and instance) are available for data markers.

Now for what we don’t support: 

  • We don’t expose non-public properties and fields to the end user. (We don’t want your top secret data getting out!)
  • We don’t YET support nested properties (%%=expenses.Description.Location), but we hope to do so in the future

So go forth and enumerate my friends!

How Not Using Stack Overflow Solves All of My Problems

$
0
0

[OfficeWriter developer and Stack Overflow user, Seth, lets us in on the thought process and psychology behind Stack Overflow, by delving into one way he uses the online community to answer his programming questions. Anything sound familiar? Or relatable? Do you use Stack Overflow in a similar fashion? Let us know in the comments section.]

stackoverflow_post_seth

Stack Overflow is a question and answer site for professional and ardent programmers. It’s a part of the Stack Exchange network of Q&A sites. Their aim is to assemble a resource of quality answers to any and all questions pertaining to programming.

There are a lot of great things about Stack Overflow:

  • It’s free.
  • The point system incentivizes people to help others.
  • The best answers have the highest visibility (usually).
  • There are experts and legendary programmers answering your questions.
  • It’s almost like a sport or competition for those answering questions.

But my favorite thing about StackOverflow is often overlooked: fear.

I can’t tell you how many times I have been so afraid that my question will get downvoted into oblivion that I end up finding the solution while writing it. (I’ll give you a hint: it’s way more than the actual number of questions I’ve posted.)

You see, posting a question on SO is like a code review to the umpteenth power. You’re opening up, not only your code, but your thoughts, explanations, and questions to be scrutinized and judged by anyone in the world. And when you throw tags on your question, you’re basically begging people who know a lot about the subject to come and take their turn.

Also, an increasing number of companies list jobs on careers.stackoverflow, and even more companies have asked me if I have an SO profile…that’s pretty daunting. Companies may be looking at and analyzing my knowledge (or lack thereof) to determine if I’m worthy of their employment!

Not only are prospective employers trolling about there, but the people on SO are my peers. They may end up being co-workers of mine one day. I don’t want them to think I’m an idiot!

And let’s not forget about ego. I worked really hard to get my measly ~2,000 points. It may not seem like much when compared to the Jon Skeet’s of the world, but I answer a lot of questions and get no points, and the questions I ask are usually really domain-specific and never get upvotes. It took me years to get that many points! Because I worked hard for my points, I don’t really want to give them up for senseless mistakes. (The SO community can be ruthless.)

After I write the first draft of my question, I usually go through it with a fine-toothed comb, looking for any holes that may exist in my argument/question. These are the steps I usually take:

  • Look for duplicates – There’s nothing that people will give you more trouble over than posting a question that has already been answered.  Heck, some people will even claim your question is a duplicate when it’s not even remotely similar to one they reference!
  • Examine the facts – I look over every statement I’ve made and think, “Is this a fact, or am I just assuming this?” If I realize it’s not a fact, I go back in my code and try to prove it.
  • Find holes in your question – Next, I read my question and try to think of what someone else might ask about my problem or domain.
  • Answer yourself – Then I try to come up with answers other people might try to give me and prove that those don’t work.

Usually at some point in that process I have an “ah-ha!” moment and I no longer need to ask the question, because I’ve answered it myself. So I can go back to increasing my meager-yet-hard-earned 2,000 points.


Announcing PowerPointWriter Beta

$
0
0

Join the beta

PowerPointWriter, the template-based way to merge your data with PowerPoint presentations, has arrived. Take your company data and merge it with PowerPoint to create custom presentations. We’re looking for beta testers to try out this new technology.

What is PowerPointWriter?

  • PowerPointWriter is a template-based approach to your presentations.
  • It allows you to build presentations programmatically with 5 lines of code.
  • No more add-ins. PowerPointWriter is a server-side solution to your custom presentations.

Learn more by joining the beta. You’ll receive a special reward just for signing up. Still curious? Take a quick look at our overview video!

 and 


// ]]>

VP of Development Talks PowerPointWriter

$
0
0

We’re launching PowerPointWriter, a new tool to save companies time on generating PowerPoint presentations with their own data, through their own applications. What is it exactly? How does it work? Why would you use it? We asked our VP of Product Development (and PowerPointWriter enthusiast), Sam, to give us a look at what makes this tool something to write home about.

sam_profile

1. What has you most excited about launching PowerPointWriter?

This has been a request from our customers for some time now. One of the things our customers always tell us is that they love our template-based approach to generating Office documents, and wanted this same ability with PowerPoint. So we did just that.

With PowerPointWriter’s template approach you can have things like dynamic images, tables, lists, and slides in as little as 10 lines of code.

2. What is your favorite feature being introduced?

This is definitely our RepeatSlide. Many times you are importing a dynamic set of data and the size will change. With RepeatSlide you can easily create a template file with only one slide in it, and have the slide repeat automatically to accommodate your data. For instance, you might have 100 rows of data and PowerPointWriter will automatically create 10 slides for you. Then, if your data grows to 200 rows, PowerPointWriter will create 20 slides for you automatically, and everything on your slide will be preserved!

3. Can you give us a few scenarios in which customers can use this product?

PowerPointWriter is really good at Mail Merge types of scenarios. For instance:

If you are all business:

Any type of pitch deck would be a great use case. Maybe you want to show your up-to-date sales numbers to stakeholders, management, or investors. You could make Score Reports using PowerPointWriter formulas, or certificates of completion for a course all of your employees were required to take.

If you are all fun:

Maybe you just want to show your mother-in-law photos from that vacation you didn’t invite her to (just kidding, I love my mother-in-law).

Why limit yourself? You can check out the samples page for more ideas.

4. What problems does PowerPointWriter solve?

PowerPointWriter allows you to get your data from virtually any data source, and put it into a file format that is familiar to your users.

It is easy. Our template-based approach allows you to build your report without much code.

It is designed for the server. PowerPointWriter is designed for the server, so you don’t need to have a client-side application to run your report. This is great because you get stability and performance when you need it most. You don’t even need Office. If you ever worked with server-side Office Automation, it is not fun, and Microsoft recommends you don’t do it.

How can I learn more?

Sign-up for the private beta before we release PowerPointWriter to the public. (We have a special giveaway just for registering.) Or watch a video of the new features being introduced.


Using OfficeWriter .NET on a 64-bit machine

$
0
0

What version of OfficeWriter do I need for 64-bit support?

  • Full 64-bit support for OfficeWriter’s pure .NET classes was introduced in OfficeWriter 3.9.1 (ExcelWriter 6.9.1). The OfficeWriter .NET dlls are compiled with the /anycpu flag so they will work fine on either 32-bit or 64-bit systems.
  • OfficeWriter’s COM dlls are still 32-bit. If you have old ASP.NET applications that are still using the .NET wrapper classes for ExcelWriter COM, you will need to run those applications in a 32-bit application pool or change your code to use the pure .NET objects. See Using OfficeWriter COM.

What is the difference between the 32-bit and 64-bit installers?

  • There are no significant differences between OfficeWriter’s 32-bit and 64-bit installers. Both contain the same .NET dlls which are compatible with both 32-bit and 64-bit systems.
  • The 64-bit installer will create the OfficeWriter program folder in Progam Files rather than Program Files (x86)
  • You can run the 32-bit installer on a 64-bit OS. However if you are installing OfficeWriter in SSRS integration mode, the 32-bit installer may have trouble finding a 64-bit instance of SSRS.
  • There is no problem manually deploying files from a 32-bit installation to a 64-bit machine

How to Send OfficeWriter Output in an E-mail

$
0
0

Sending OfficeWriter output in an e-mail is possible while either using OfficeWriter in .NET or with SSRS integration. When using the OfficeWriter .NET API, you can use the .NET MailMessage class to send your OfficeWriter output as an attachment in an e-mail. In SSRS, you can send the output as a subscription-based e-mail.

Sending OfficeWriter Output Using the .NET MailMessage Class

In order to send OfficeWriter in an e-mail output using .NET, you need to use the MailMessage object. If you save the workbook,  document, or presentation to a stream, you can create an attachment out of the file in the stream. This attachment can be added to the MailMessage object and sent to the workbook’s or document’s end users.

//Open Word Template
WordTemplate wt= new WordTemplate();

//Do some databinding and processing here
//YOUR CODE HERE

//Create a file stream that will save the output file on the server
FileStream myStream = new FileStream(@"C:\temp\outfile.xlsx", FileMode.Create);

//Save the output to the stream
wt.Save(myStream);

//Create an Attachment of the file in the stream
Attachment myAttachment= new Attachment(myStream, "output.xlsx");

//Create a mailmessage obj
MailMessage mailObj = new MailMessage("From Address", "To Address", "Subject", "Body");

//Add the attachment
mailObj.Attachments.Add(myAttachment);

//Connect to the server that will send the email
SmtpClient SMTPServer = new SmtpClient("thenameofyourhost");

//Set credentials
SMTPServer.UseDefaultCredentials = true;

//Try sending
try
{
    SMTPServer.Send(mailObj);
}
//Basic error handling
catch (Exception ex)
{
    Response.Write(ex.ToString());
}

Sending OfficeWriter Output Using a SSRS Subscription

If you are integrating OfficeWriter with SSRS, it also possible to send OfficeWriter output by using subscriptions. Be aware that the credentials to run the report must be stored inside of the report.

  1. After uploading your report to the SSRS server, open Report Manager
  2. Find your report and from the Drop Down, select “Manage”
  3. In the left-hand menu, select “Subscriptions” and then “New Subscription”
  4. Fill out the form, including:
    1. Who you want to send the report to
    2. When you want to send it
    3. What parameters the report should run with
    4. Be sure to select either “Excel designed by OfficeWriter” or “Word designed by OfficeWriter” as the rendering format.
      RenderFormat
  5. Click “Ok”
  6. Your new subscription should now appear in the Subscriptions list for your report and will run at the time you specified.

How to Avoid Extra Page at Document End When Using WordTemplate

$
0
0

When you want part of your WordTemplate document to repeat on every page, you must set a PageBreak on that page. However, if you set a default PageBreak, Word will automatically insert what is called a Page Break After. The Page Break After  will result in an extra page at the end of your document. In order to fix this, you will need to set a Page Break Before  at the beginning of the page you want to repeat.

Instructions on Setting a Page Break Before

  1. Click on the top left corner of the page where you want your page break to occur.
  2. In the “Home” tab, there should be a “Paragraph” section. Click the arrow on the bottom-right of the Paragraph Section.
    Screenshot 2014-06-20 11.30.19
  3. Go to the “Line and Page Breaks” tab and check the “Page Break Before” option.
    Screenshot 2014-06-20 11.35.51
  4. Click “Ok”.

Word will have now inserted a PageBreak before at the spot where you cursor lay in the document. Your document should now generate the correct number of pages.

How to Use Process Monitor (ProcMon) to Troubleshoot Web Applications

$
0
0

Process Monitor is a great tool that can help you troubleshoot applications when error messages alone just aren’t enough information to solve a problem. Process Monitor works by logging in-depth about the actions of particular processes. It will give you in-depth information about file access, registry access, threading, and permissions. In this how-to tutorial, we will show you how to collect information on the process that ASP and ASP.NET web applications run on – wpw3.exe.

Step 1:  Download Process Monitor

You can download Process Monitor here. http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

Step 2:  Open Your Web Application

Go to the page in your web application before your error occurs. You need to be easily able to trigger the event that causes the error while ProcMon is running to avoid collecting too much information.

Step 3:  Monitor the w3wp.exe Process

  1. Reset the filter by clicking Filter -> Reset Filter
  2. Add the w3wp.exe process to the filter by going to Filter -> Filter…
  3. A dialog box will appear.
  4. Create a rule that says “Process Name is w3wp.exe”
    Process is w3wp.exe Rule
  5. Click “Add”
  6. Click “Apply” and then “OK” to exit the Dialog

Step 4:  Collect Information from ProcMon

  1. Please make sure that the Capture icon (shaped like a magnifying class) is enabled. There should NOT be a red “X” through it.
    Capture Events
  2. Go to your web application and trigger the error.
  3. Once the error occurs, go back to ProcMon and click the Capture Icon to stop capturing events.

Step 5:  Examine the ProcMon Logs

  1. The first thing you should do when examining the logs is to see if anything in the “Result” column is not “SUCCESS”. Please take notes of any warnings or errors.
  2. Once you find the errors, determine if they are relevant to your issue.
  3. If you would like to save the logs, you can by going to File -> Save.

Adding SSRS Formulas, Global Variables, and Parameters to Your Designer .NET Report

$
0
0

The original OfficeWriter Designer allowed users to add the equivalent to SSRS expressions in their Designer report by using a feature built-in to the Designer called the formula manager. However, in recent months, SoftArtisans has released a new, beautiful, more robust designer called the Designer .NET. The only complication is that the Designer. NET does not yet have a built in formula manager. Fortunately, you can still add many calculated values, parameters, and other report information to your report by using SSRS calculated fields in Visual Studio.

NOTE:  Currently Reporting Services does not allow Visual Studio calculated fields to contain user-defined variables, aggregate, RowNumber, RunningValue, Previous, or lookup functions when rendering the report.

Adding Expressions to Your DataSet

  1. Open your RDL in Visual Studio.
  2. Right click the dataset you want to add the expression to and click “Add Calculated Field…”
    Add a Calculated Field...
  3. A dialog should appear with two columns: Field Name and Field Source.
  4. Enter any name into Field Name
  5. Click the fx symbol to create a formula for the value of your field.
    Click the "fx" button
  6. In the new dialog, you decide what formula you want your field to express. Let’s say you want to display a parameter in your report. In this case, you would click “Parameters”, and then double-click the parameter you want to add. You should now see a formula at the top of the window.
    Add a parameter by double-clicking the one you want to add
  7. Hit “Ok” and exit out of the dialogs.
  8. Save your RDL and open it in the Designer .NET.
  9. While designing the report, add the data marker that corresponds to your expression into your report.
    ExpressionDataMarker
  10. When you’re finished designing the report, deploy it to SSRS from the OfficeWriter Designer .NET


Saving Your Report’s Data in CSV Format

$
0
0

If you have ever filed a support incident with SoftArtisans Technical Services concerning your OfficeWriter reports, you know that one of the most important steps in resolving an issue is having a Technical Services Engineer reproduce it. While there are many components to reproducing a customer issue, one of the most critical aspects is having sample data to run the affected report with. Unfortunately, this can be a special challenge because a Technical Services Engineer does not have access to your data sources. The inability to run the report can delay or even halt Technical Service’s ability to troubleshoot an issue. However, do not fret, as CSV files can save the day!

Steps to Save Your Report Data as a CSV File

  1. Download the attached template Collecting_Data_For_SA. The template will allow you to gather data for up to 10 datasources with up to 35 columns each.
  2. Run this template through your application:
    1. If you have a custom web application that uses ExcelTemplate: run this template through your application.
    2. If you have a custom web application that uses  ExcelApplication or Word Application: run this template through your application using ExcelTemplate with code that looks something like this:
      ExcelTemplate xlt= new ExcelTemplate();
      
      //Open the collecting_data_for_sa template
      xlt.Open("collecting_data_for_SA.xlsx"));
      
      //Bind each of your datasources to the template
      xlt.BindData([YOUR DATA SOURCE], "Something", xlt.CreateDataBindingProperties());
      xlt.BindData([YOUR DATA SOURCE2], "Something2", xlt.CreateDataBindingProperties());
      xlt.BindData([YOUR DATA SOURCE3], "Something3", xlt.CreateDataBindingProperties());
      
      xlt.Process();
      xlt.Save("data_collected.xlsx");
    3. If you are using SSRS integration:
      1. Create a copy of your affected RDL.
      2. Open the copy RDL in the OfficeWriter Designer or OfficeWriter Designer .NET for Microsoft Excel.
      3. Click “Import Template” in the Designer tab and overwrite your existing template with the collecting_data_for_sa file.
      4. The copy rdl should now contain the collecting_data_for_sa template.
      5. Upload the rdl to SSRS and run the report.
  3. Send the results to SoftArtisans Technical Services

How to Calculate Unsupported or Custom Formulas on the Server with ExcelWriter

$
0
0

Beginning in OfficeWriter 9.1, ExcelApplication’s calculation engine will offer the ability to implement custom formulas. This feature should prove helpful to users whom would like to calculate their own custom formulas or calculate formulas not currently supported by ExcelWriter on the server using ExcelWriter. This tutorial will show you how to implement these formulas.

Creating Your Own Formula

  1. Create a class that implements an interface provided by ExcelWriter called IFunction. The IFunction interface implements a method called Calculate.
  2. Inside of your class, create the Calculate method with this signature:
    FunctionValue Calculate(IList<FunctionValue> args, Cell currentCell)
  3. Inside of the Calculate Function, code the logic of the formula you would like to implement.
    1. The first argument of Calculate is a list of FunctionValue objects. FunctionValue objects are how we pass values in and out of formulas. FunctionValues have several properties available to them, so please see the documentation for more information about how you can use the properties in your formula logic.
    2. The second argument of Calculate is the cell that contains the formula. Please see the documentation for more information about Cell objects and their available properties and methods.

Registering the Formula with ExcelWriter

  1. Once the formula is written, register the function using Workbook.RegisterCustomFunction.
    WB.RegisterCustomFunction("MyFormula", new MyClass());

Calculating the Formula and Removing it From a Workbook

Once your formula is registered, you can use WB.CalculateFormulas to have ExcelWriter calculate the value of any cells that use the formula in your Workbook. If you are generating Excel output using ExcelApplication.Save, please note that if you have implemented a custom formula that it is not recognized by Microsoft Excel, the end user will not see the calculated values in the output workbook when opened in Excel. To get around this issue, you can use Workbook.RemoveFormulas or Worksheet.RemoveFormulas to remove the formulas from the worksheet or workbook, while leaving the last calculated values in the cells.

Here is an example of what your finished code should look like:

public class sample
{
   MyMainMethod()
   {
      ExcelApplication xla = new    ExcelApplication(ExcelApplication.FileFormat.Xlsx);
      Workbook WB = xla.Create(ExcelApplication.FileFormat.Xlsx);
      WB[0]["A1"].Formula = "=COUNTARGUMENTS(4, 5, 6)";
      WB.RegisterCustomFunction("COUNTARGUMENTS", new Formula());
      WB.CalculateFormulas();
      //Optionally remove all formulas from the workbook, so only values remain. This is good in case you are using a custom formula that Excel will not be able to calculate.
      WB.RemoveFormulas();
      xla.Save("output.xlsx");
   }
}

class Formula : IFunction
{
   public FunctionValue Calculate(IList<FunctionValue> args, Cell cell)
   {
      //Returns the number of arguments
      return new FunctionValue(args.Count);
   }
}

How to Save an Excel Workbook to a PDF Document

$
0
0

OfficeWriter 10.0 introduces the ability to save a Workbook, Worksheet, or Area to a PDF document. This makes it possible to produce a searchable, vector-format rendering of your spreadsheet.

Using the Imaging Extension DLL

The PDF functionality is included in the rendering extensions DLL (SoftArtisans.OfficeWriter.ExcelWriter.Imaging.dll). The first thing you will need to do is include this DLL as a reference in your project in Visual Studio. You will also need to tell the compiler to use the imaging namespace in your source file. This can be accomplished by adding a using statement to the top of the file where you want to save a PDF document:

using SoftArtisans.OfficeWriter.ExcelWriter.Imaging;

Setting up your workbook

In order to save an Excel workbook to a PDF document, you first need a workbook with contents in it. For this example, let’s create a simple workbook with three worksheets:

ExcelApplication xla = new ExcelApplication();
Workbook WB = xla.Create(ExcelApplication.FileFormat.Xlsx);
Worksheet ws0 = WB[0];
Worksheet ws1 = WB.Worksheets.CreateWorksheet("Sheet2");
Worksheet ws2 = WB.Worksheets.CreateWorksheet("Sheet3");

ws0[0, 0].Value = “Sheet 1, Cell A1”;
ws1[0, 0].Value = “Sheet 2, Cell A1”;
ws2[0, 0].Value = “Sheet 3, Cell A1”;

For this example, we are just exporting some cells with text in them. However, the rendering extensions support more dynamic content as well, such as cell formatting, charts, images, comments, or conditional formats. We could also use a workbook that we opened from a file, that already had contents and formatting applied.

Saving a PDF document

There are three ways to save a PDF document: through the workbook, through a worksheet, or through a specific area. Specific PDF rendering options can be specified by setting a worksheet’s PageSetup properties; this will be covered in a later tutorial. If you have not set any of the worksheet’s PageSetup properties, then default settings will be used.

You can save multiple PDF files from one workbook. First, let’s save multiple worksheets to a single PDF document. This can be achieved by using the Workbook.SavePdf method. The first parameter is a Boolean; if this is set to true, then only selected worksheets will be saved. Otherwise all visible worksheets will be saved.

For this example, lets save the first and the third worksheet to a single PDF document. Continuing from the code above, we can achieve this with the following two lines of code:

WB.Worksheets.Select(new object[]{0, 2});
WB.SavePdf(true, “MultipleWorksheets.pdf”);

We can also save the remaining worksheet to a separate PDF file containing only the contents of that worksheet:

ws1.SavePdf(“sheet2.pdf”);

This allows to either generate multiple PDF documents, each containing one worksheet, or a single PDF document containing multiple sheets.

Calls to SavePdf must be made before saving a workbook to an xlsx/xlsm file. Once you have exported all of the PDF documents that you want, you can then also save the workbook to an Excel file as you normally would:

xla.Save(WB, “workbook.xlsx”);

Putting it all together

Here’s what the final code looks like:

using SoftArtisans.OfficeWriter.ExcelWriter;
using SoftArtisans.OfficeWriter.ExcelWriter.Imaging;

public class SampleProgram
{
public static void Main(string[] args)
{
ExcelApplication xla = new ExcelApplication();
Workbook WB = xla.Create(ExcelApplication.FileFormat.Xlsx);

// Set up the workbook with some content
Worksheet ws0 = WB[0];
Worksheet ws1 = WB.Worksheets.CreateWorksheet(“Sheet2”);
Worksheet ws2 = WB.Worksheets.CreateWorksheet(“Sheet3”);
ws0[0, 0].Value = “Sheet 1, Cell A1”;
ws1[0, 0].Value = “Sheet 2, Cell A1”;
ws2[0, 0].Value = “Sheet 3, Cell A1”;

// Select two worksheets and save them to a single PDF document
WB.Worksheets.Select(new object[]{0, 2});

// The ‘true’ argument tells the rendering method to only save worksheets
// that are currently selected. If it were ‘false’, then all worksheets
// would be saved to the PDF.
WB.SavePdf(true, “MultipleWorksheets.pdf”);

// Save one worksheet to a separate PDF
ws1.SavePdf(“sheet2.pdf”);

// Finally, save the workbook to an Excel file in case we need to edit it later
xla.Save(WB, “workbook.xlsx”);
}
}

Save PDF file to HttpResponse

$
0
0

In a previous blog post we discussed how OfficeWriter 10.0 introduced the ability to save an Excel workbook to a PDF document. When working in a web environment it is common to want to send the generated file to the browser for your end user to download and view on their own machine.

Step 1:
Generate your workbook. A very simple example might be:

var xla = new ExcelApplication();
var wb = xla.Create(ExcelApplication.FileFormat.Xlsx);
var ws = wb[0];
ws.Cells[0, 0].Value = "Hello";
ws.Cells[0, 1].Value = "World!";

Step 2:
Define a helper method to write the file byte to the current response stream:

public static void WriteFileToResponse
(HttpContext context, byte[] bytes, string fileName)
{

var bytesLength = bytes.Length.ToString(CultureInfo.InvariantCulture);
var response = context.Response;
response.Clear();
response.Buffer = true;
response.AddHeader("Content-Length", bytesLength);
response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
response.ContentType = MimeMapping.GetMimeMapping(fileName);
response.BinaryWrite(bytes);
response.Flush();
response.End();
}

Step 3:
Save the PDF to a memory stream and call our helper method we just defined. This has the benefit of avoiding disk IO. This may vary if your application actually needs to persist the generated PDF.

using (var memoryStream = new MemoryStream())
{
var fileName = "generatedfile.pdf";
wb.SavePdf(false, memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
WriteFileToResponse(HttpContext.Current, memoryStream.ToArray(), fileName);
}

And that’s it!

How to Use PageSetup Options When Saving to a PDF Document

$
0
0

When saving Excel worksheets to a PDF document using the PDF rendering extension methods introduced in OfficeWriter 10.0, it is often useful to be able to specify details about the resulting PDF document, or about how the rendering should behave.  This is achieved by setting properties on the worksheet’s PageSetup property before calling the SavePdf method.  This tutorial will walk through that process.

Setting up your worksheet

For this example, we will open an existing workbook, in order to save the first worksheet of the workbook to a PDF document:

ExcelApplication xla = new ExcelApplication();

Workbook WB = xla.Open(“input.xlsx”);

Worksheet worksheetToSave = WB[0];

 Specifying page properties

 Using the worksheet’s PageSetup property, we can specify the page size, orientation, and margins.  These properties will be reflected in the final PDF document:

worksheetToSave.PageSetup.PaperSize = PageSetup.PagePaperSize.Legal;

worksheetToSave.PageSetup.Orientation = PageSetup.PageOrientation.Landscape;

worksheetToSave.PageSetup.TopMargin = 1.5; // Specified in inches

Setting a header and footer

The PageSetup property can also be used to set a header or footer.  The header and footer will be printed on each page of the PDF:

HeaderFooterSection.Section hfSection = HeaderFooterSection.Section.Center;

worksheetToSave.PageSetup.GetHeader(hfSection).SetContent(“Header text”);

Specifying rendering options

Other PageSetup properties are useful for specifying how the content should be rendered to the PDF document.  For example, we can make the content smaller than normal by using the Zoom property, specify the order in which pages should appear in the PDF document, and print all of the cell comments at the end of the document by setting the relevant properties on the worksheet:

worksheetToSave.PageSetup.Zoom = 50; // Specified as a percentage

worksheetToSave.PageSetup.UseZoom = true;

worksheetToSave.PageSetup.PrintOrder = PageSetup.PagePrintOrder.DownThenOver;

worksheetToSave.PageSetup.PrintComments = true;

worksheetToSave.PageSetup.PrintCommentsAtEnd = true;

There are additional PageSetup properties that may prove useful; for a complete list, see the PageSetup documentation.

Saving the PDF document

Once you have set all desired PageSetup options, you can then save the worksheet to a PDF document:

worksheetToSave.SavePdf(“output.pdf”);

If you want to save multiple PDF documents from the same workbook, but with different options set, you can repeat this process.  For example, after saving one PDF document, you could then change the PaperSize property to a different size of paper, and then save a second document.  The updated properties will be reflected in any subsequent calls to SavePdf.

When saving an entire workbook to a PDF, each worksheet is rendered using its own PageSetup properties.

Viewing all 140 articles
Browse latest View live