Exe size

I want to read csv files and xls and xlsx files. When I add VCL.FlexCel.Core, FlexCel.XlsAdapter to my uses clause and write


  FXLS: TExcelFile;
...
  FXLS := TXlsFile.Create(False);

my executable size increases from 17.5 MB to 20.5 MB. Is this to be expected?

Thanks

William

Hi,

Yes, this can be expected.The thing is, when you instantiate a TXlsFile object, you are embedding a mini-excel into your application. Even if you are only going to read simple files, we can't know if for example the xls/x file you are reading will contain say a =PPmt(...) function, so we need to have support for over 300 functions that your file might contain, and we need to be able to recalculate them. So the full recalculation engine is included. Same for the features in the xls/x file: Maybe you are never going to read a chart, but we can't know that when you create a TXlsFile object that you are never going to read charts, so the full chart engine is included too. Same for xlsx or csv, maybe you are only going to read xls files, but we don't know it, so the csv and xlsx engines need to be linked too. (and our own optimized xmlreader, xmlswriter and zip classes, to support xlsx). OR the encryption engine, maybe you are never going to read or write encrypted xls or xlsx files, but we can't know it, so the encryption engine is linked in the exe too.
 
A lot of stuff needs to be included, because we can't know if that stuff will be in the files you are trying to read or not. FlexCel 3 didn't support recalculatio or xlsx or encryption, so it could be smaller, but FlexCel 6 supports that all and more.

Besides the really big number of features we need to support because they might be in the files, there is also a problem with the Delphi compiler not optimizing enough, but we have tried to reduce that to the minimum. For example we use a lot of generics, and in Delphi generics can produce an incredible bloat (this being the reason why exe files get bigger in each delphi version, each delphi version replaces more and more TLists by TList<T>. This is also the reason FireMonkey is so big). But in our case, we have implemented our own lightweight generic classes, so we use our own TuList <T> instead of the default TList<T>. Our own classes are not only faster than the ones in Delphi, but they are also much smaller, and implement folding: Folding means that all list and dictionaries of objects share the same implementation and don't bloat the code, as the built in delphi classes do. 

We've put a lot of effort in making FlexCel as small as possible, and I think we've arrived to a good compromise. 3mb extra in your exe isn't that much for all the functionality built in, and it is much less than the about 8mb that the earlier FlexCel 5 version added, before we spent a lot of time making it as small as we could make it. And much less than the 1gb Excel itself uses if you install it. And most of those 3mb are actually needed functionality, not generics/rtti bloat as it used to be before we implemented our own containers.

Thanks Adrian.

Hi,

I realize this is 12 years later but I'm new to FlexCel and my application exe grew 7.3MB when I added FlexCel. All I do is read and write simple Excel files. Isn't there anything that can be done? I have many users running over a VPN and the larger application takes a noticable longer time to load.

Sadly the answer is still the same. You might be reading simple files, but FlexCel can't know that when it is opening the file. That file could include conditional formatting, charts, and a lot of other stuff that we need to understand and preserve. If you insert a row in that file, we need to modify the chart so it points to the new range after we inserted the row. etc.

Now, this being said, I just tried it here with a new file (Delphi 12, Release builds), and I get:
Empty project: 2.371mb
Project with FlexCel that opens, modifies and saves a file: 7.017

So the increase should be 4.6mb, not 7.3mb. Still big, I know, but not 7 mb
It is also more than the 3mb in the original post, but we added quite a lot of stuff in those 12 years... all that code counts. Seriously, just go to where we were 12 years ago:

and try scrolling up... I am obsessed with getting every detail right, but every thing we add, adds some lines of code, and some extra size to the exe. Still, I prefer to have it right even if big.

I can't really give you a solution (There is a saying "everyone uses a 10% of Excel, but everyone uses a different 10%"). And even if you don't realize, your simple files might not be so simple. Many times they include stuff that you aren't even aware you are using. And with people generating spreadsheets with AI, this is going to get an order of magnitude worse. But some ideas:

  • I develop FlexCel myself over a VPN (sometimes at the other side of the world, I am in south america and develop frequently from europe or australia). 7mb shouldn't affect that much (I run full RDPs over the VPNs), maybe there is something you can do to improve the VPNs. I know it might not be possible, but I mention it because 7mb in today's world shouldn't affect that much. An image in a webpage is bigger, and there is some caching that can be done so you aren't constantly downloading that file.

  • Maybe you are linking also the rendering engine? If I add "FlexCel.Render" to the mix, the size goes up to 7.892mb (an increase of 5.5 mb over an empty file). FlexCel.Render is needed to export to pdf, etc, and that adds another big layer of complexity over it (FlexCel has to now know how to convert the description of the chart into an image to put inside a pdf. And it doesn't matter that the chart is "simple", when you compile the app in your machine, FlexCel doesn't know how simple are the charts it will have to render). The main issue here is that you will need FlexCel.Render if you are autofitting rows or columns, and if that is the case, there is not much to do. But if you aren't, verify that you aren't using FlexCel.Render anywhere, as it will shrink the size (and double-verify you aren't autofitting stuff, because that will break at runtime if you remove FlexCel.Render from the app)

I was also thinking that you could use runtime packages to, even if not reduce the size, keep the packages cached in users machines, but that will probably be worse that what we are trying to solve (a single exe is a great thing).

Another thing to consider: Normally uncompressed size isn't that important, because it will travel compressed in the places that are slow (like the vpn, or when you download it from somewhere).
Comparing now the compressed empty app with the compressed "full app" (including rendering), I see a difference of 2.3 mb (931kb against 3.240mb). This is using standard zip compression, of course it would be even smaller if using better compression.