If a language inherently supports exceptions, then it is preferred to throw exceptions and the clients can catch the exception if they do not want it to result in a failure. In fact, the clients of your code expect exceptions and will run into many bugs because they will not be checking the return values.
There are quite a few advantages to using exceptions if you have a choice.
Messages
Exceptions contain user readable error messages which can be used by the developers for debugging or even displayed to the users if so desired. If the consuming code cannot handle the exception, it can always log it so the developers can go through the logs without having to stop at every other trace to figure out what was the return value and map it in a table to figure out what was the actual exception.
With return values, there is no additional information can be easily provided. Some languages will support making method calls to get the last error message, so this concern is allayed a bit, but that requires the caller to make extra calls and sometimes will require access to a 'special object' that carries this information.
In the case of exception messages, I provide as much context as possible, such as:
A policy of name "foo" could not be retrieved for user "bar", which was referenced in user's profile.
Compare this to a return code -85. Which one would you prefer?
Call stacks
Exceptions usually also have detailed call stacks which help debug code faster and quicker, and can also be logged by the calling code if so desired. This allows the developers to pinpoint the issue usually to the exact line, and thus is very powerful. Once again, compare this to a log file with return values (such as a -85, 101, 0, etc.), which one would you prefer?
Fail fast biased approach
If a method is called somewhere that fails, it will throw an exception. The calling code has to either suppress the exception explicitly or it will fail. I have found this to be actually amazing because during development and testing (and even in production) the code fails quickly, forcing the developers to fix it. In the case of return values, if a check for a return value is missed, the error is silently ignored and the bug surfaces somewhere unexpected, usually with a much higher cost to debug and fix.
Wrapping and Unwrapping Exceptions
Exceptions can be wrapped inside other exceptions and then unwrapped if needed. For example, your code might throw ArgumentNullException
which the calling code might wrap inside a UnableToRetrievePolicyException
because that operation had failed in the calling code. While the user might be shown a message similar to the example I provided above, some diagnostic code might unwrap the exception and find that an ArgumentNullException
had caused the issue, which means it is a coding error in your consumer's code. This could then fire an alert so the developer can fix the code. Such advanced scenarios are not easy to implement with the return values.
Simplicity of code
This one is a bit harder to explain, but I learnt through this coding both with return values as well as exceptions. The code that was written using return values would usually make a call and then have a series of checks on what the return value was. In some cases, it would make call to another method, and now will have another series of checks for the return values from that method. With exceptions, the exception handling is far simpler in most if not all cases. You have a try/catch/finally blocks, with the runtime trying its best to execute the code in the finally blocks for clean-up. Even nested try/catch/finally blocks are relatively easier to follow through and maintain than nested if/else and associated return values from multiple methods.
Conclusion
If the platform you are using supports exceptions (esp. such as Java or .NET), then you should definitely assume that there is no other way except to throw exceptions because these platforms have guidelines to throw exceptions, and your clients are going to expect so. If I were using your library, I will not bother to check the return values because I expect exceptions to be thrown, that's how the world in these platforms is.
However, if it were C++, then it would be a bit more challenging to determine because a large codebase already exists with return codes, and a large number of developers are tuned to return values as opposed to exceptions (e.g. Windows is rife with HRESULTs). Furthermore, in many applications, it can be a performance issue too (or at least perceived to be).
If you really want something that works well for you, then I suggest you get used to the idea of "unnecessarily complex"... that's the nature of dealing with Microsoft Office file formats.
I (sort of) like your idea of "blocks"... I would make sub-classed block objects, like Table, with Columns and Rows independent of the notion of cells. Then use your block engine to convert these to XSLS files.
I've used the OpenXML SDK successfully in the past, but don't try to read the documentation and start from scratch. Instead, create an exact copy in Excel of what you want, save it, and inspect it using the provided Document Reflector tool. It will give you the C# code you need to create the document, which you can then learn from and modify.
Best Answer
I've written this in C, so I can't guarantee that it'll cut-and-paste into Java.
If you're certain you want to retry DoA only once, use can use one line:
If you want the option of more than one retry, use this loop.
Edit: If you really cannot make time to extract
DoA
andDoB
, then try the following block. Remember that comments are your friend: