“Entries cannot be opened multiple times in Update mode” error in SpreadsheetLight

So I finally got to work on upgrading SpreadsheetLight to .NET Standard 2. The main code changes revolve around the System.Drawing assembly reference. Changing the reference to the NuGet System.Drawing.Common package solved most of it. Maybe I’ll tell you about the handful of System.Drawing related changes in another article.

But the error that gave me minor heart attacks was this one:
“Entries cannot be opened multiple times in Update mode”

Going through the code, it’s the point where SpreadsheetLight saves the whole spreadsheet, and then opens it up again for minor “enhancement” fixes. These enhancements were to change the internal relation links in the file to be how Excel writes them, rather than what the Open XML standard uses.

It’s not wrong, it’s just that I want to align whatever SpreadsheetLight creates to be as close to what Excel outputs as possible.

The idea is that a spreadsheet that Excel outputs works on LibreOffice Calc and on Apple Mac software devices such as iPhone and iPad and Mac Books.

Apparently what the Open XML SDK outputs as a default conforms to the Open XML Standard, but doesn’t quite work in iPhone/iPad (the spreadsheet doesn’t open properly in iPhone/iPad).

So as the simplest of fixes go, I just commented that entire chunk of code. Making sure the SpreadsheetLight outputs spreadsheets that will work in Excel on Microsoft Windows is the bare minimum criteria. Everything else is an extra benefit.

SpreadsheetLight version 3.5

So I finally got SpreadsheetLight onto the .NET Standard/Core train. Get yours here.

The reason it took me so long is that I was still recovering from personal and business stuff. And when I saw I needed to set up Visual Studio 2019 (2017 back then), and I had to check if my code was compatible with .NET Standard/Core, that was too much…

Another reason was whether I should still depend on the Open XML SDK DLL, or just bite the bullet and depend solely on the official Microsoft DocumentFormat.OpenXml Nuget package.

In the end, based on emails sent to me, and observation of general software development trends, I just went ahead and depend on Nuget packages. Because the urgency and cost of me continuing to stall was just too great.

The main code incompatibility, so to speak, has to do with the absence of System.Drawing in the .NET Standard framework. SpreadsheetLight uses the Drawing assembly to check text widths and heights for the purposes of autofitting columns and rows. I didn’t want to have to find an alternative method…

Until I found that Microsoft has an official Nuget package System.Drawing.Common which mimics (or is exactly?) the System.Drawing but in .NET Standard/Core form. Woobdeedoo!

Yes, I’m like 2 years too late. I might possibly have lost developers who jumped ship and used other libraries. I have emails of developers/users asking for a .NET Standard/Core version, which means they are kind of forced to keep their applications running on .NET Framework 4 because of me (probably high opinion of myself, but a sense of self-importance drove me to action, so maybe it’s not that bad if it’s not publicly known. Oh wait, I just told you…)

So get a copy of the latest and greatest version of SpreadsheetLight and I’ll talk to you another time.

Food skimming app that failed

My business failed a few years ago. (It is raining and thunder is rolling as I’m writing this, which is ominous and eerily fitting at the same time)

My business partners were not helpful. I did most of the work and they expected to reap the benefits. And that’s all I’m going to say about that.

Anyway, it was an app/software that we would try to sell to food sellers. Anything from mom-and-pop cafes to restaurants. What it does is list the available food items. Features include picture of the food item, the price, nutritional information.

I pointed out to my business partners that while the app helped the customers, it didn’t do much for the food business owners. In fact, it would probably add more work load to them.

The most glaring omission is the ability to integrate with their payment systems. And boy that was a big one. But my business partners apparently thought that was a small issue.

The ideal app had to coordinate things like, allowing the customer to order, have the order sent to the kitchen, and process payment. And the app couldn’t do any of that. Which makes the app kind of pointless.

I struggled with keeping the development up for about a year. Without sufficient help from my business partners, I couldn’t keep it going anymore, financially and creatively. So I shut the company down (and even that was a rollercoaster of a ride)

I’ve written a little of my company’s product before, but I thought maybe I’d talk a little bit more about it. If only to bring closure.

So I bought a domain for it. I had to think up a name for it (I came up with FoodSkim. I know it’s not creative or hip but I was out of juice back then). But I had to eventually let them disappear into the past. What’s sad is I’m probably the only one who will remember them.

So when I see the new apps and services catering to food businesses, I have to wonder what would have happened had I actually managed to pull it off. I mean there’s GrabFood, FoodPanda and a whole host of other food delivery service apps. There are also many software services that do digital ordering of food, either for delivery or within the restaurant or cafe itself (one of them is Waitr app I think).

It was a painful experience, but also an enlightening one. I’m just not sure of the man I have become since then.

Rapid iterations and long running programs

So recently I have to run a program that takes a long time to complete. I don’t mean the program is slow. It’s just that whatever it’s doing takes a long time because there is a lot of data to process.

I’m talking days, stretching into almost 2 weeks.

When I was younger (and more naive), I thought pfft there could never be programs that had to run more than an hour. Computers are so fast!

I was wrong.

When I was writing my honours thesis in university, I had to write a computer virus infection simulation program (it forms the basis of my thesis results). I had nodes serving as computers. I put edges in the graph (mathematical term for network) as connections between the “computers”. Then I let my virus logic run amok in the network.

When I found out how long it took to complete, or at least reach a stable infection equilibrium, I was shocked. Dismayed. Dread even. It took slightly over an hour to complete. Sometimes two hours.

So I’d run the program and go for lunch. Then come back and see what my results were. I learnt to make changes and note them down meticulously because re-running the program was expensive, time-wise.

And so it is with my current long-running program. One mistake, or one forgotten consideration, or one miswritten line of code, and I’d have to rerun the program. By that time, I might have wasted a day.

As they say, measure twice cut once.

Find the real problem

Complicated systems require deeper questionsA while ago, I was asked to add some new features to an existing software system. The request seems straightforward, but my developer senses were tingling.

The user wanted to track if a student had taken a particular course. Which would have been simple but because I know students, people fail courses. So I asked if a failed course should still be noted down.

“Yes!” she said.

Well then, it’s no longer a simple single instance. The system had to track the student’s progress until the student passes. I mean if a student takes more than one attempt to pass the course, there are bigger problems. But they’re not the software system’s problem *grin*

In general, when I’m presented with a problem, I try to understand if there’s a bigger and more fundamental problem lying underneath. I don’t mean that you have to question every single question or problem once or thrice.

Sometimes your buddy asking you what you’d like to eat is simply that. And not that your buddy is insinuating that you are indecisive and is still angry the last time he picked out a place.

But you know, complicated systems like software or climate or this current pandemic require more thought into both questions and answers.

Physical and mental stress

I’ve been writing code for a long time.

I wasn’t a computer science student. When I was in university, I studied applied maths, because that was what I was good at and luckily, interested in as well. Then there was this side module that taught the C language. And that’s how I learnt my first proper programming language over 20 years ago.

(I self taught myself BASIC with a toy computer in my early teens, but that’s another story)

Over time, the incredible bursts and protracted periods of programming energy morphed into shorter chunks of methodical thinking and planning. Life as a teenager and young adult is also simpler than the 30’s and 40’s.

Life takes its toll. Few programmers talk about it, but there’s a mental strain, especially with you know, life happening. I’ve had my fair share of mental stress, so let me tell what worked for me.

Magnesium supplementation helped. As had this herb called ashwagandha. I also do meditation and breathing exercises when I get to do them. Continuing the food angle, I used to take weight gainer powders. I’m a skinny guy and found it hard to put on mass. Later in life, I realised I wanted to put on muscle, not just meat on my body.

So I started working out. Being the shy guy, I bought dumb bells and exercised at home. Some progress but that’s probably beginner gains.

Fast forward to now, and I’m doing mostly body weight exercises. My current regime is 100 pushups as the base. I have a very loosely defined set of workout exercises, mostly for convenience and ease. If it takes too much to set up for the exercise, I’m just not gonna do it…

I found the physical exertion to be necessary. My body needs to expend energy to be somewhat fatigued or I’ll feel cranky. This ties in to the stress release, both physical and mental.

I’ve been writing code for a long time. Which also means I’ve been living for a fair bit. If you’re a young person, by all means ride that exhilaration of energy. Just also know that it’s ok if you run out of steam and needs to recharge.

Messy and chaotic changes

So I never thought Singapore would be in lockdown mode for several months this year.

The year started well enough. I was transferred from the artificial intelligence department to the cyber security department. New technologies to learn. New people to befriend.

Then this pandemic thing happened.

Within a couple of months, the virus raged across the world. And Singapore took decisive action and locked the whole country down. Everyone was to stay home except for essential services or emergency situations.

The panic buying and queues were laughable if the situation weren’t so dire.

Professionally, I had to switch from the .NET world to the Ubuntu/Linux world. The C# and .NET libraries gave way to Python and vi (yes I do know how to exit from vi, thank goodness). Visual Studio autocompletion and SQL Server gave way to command line grep and PostGreSql/MySql.

I’d be lying if I said I was ok mentally speaking. These past few months had been psychologically and mentally taxing for everyone.

To climb out of this mental hole, I put in more effort into two specific activities: Russian language acquisition and physical fitness.

Hello comrade!

I had been learning Russian for a couple of years now. Mostly with the app Duolingo. But I discovered I wasn’t making a lot of progress. The lockdown both highlighted my inadequacy and gave me the opportunity to push myself.

So I switched over to the app Lingvist for new vocabulary and spaced repetition. I created a separate YouTube account with just Russian content. The idea is to see, hear and read as much Russian content as possible, and in as comprehensible a manner as possible (aka comprehensible input).

I made more progress in two months than in two years.

Body recomposition

I also changed my workout routine. I’ve never gone to the gym to exercise. I trained with dumbbells at home. I’ve done so since my early 20’s.

So I’ve been “training” for a long time. And I’m still not jacked! I blame myself. What the blyat have I been doing?

So I switched over to body weight exercises. And the muscle growth finally came and shattered my plateau. My biceps and triceps are more pronounced. I’m filling up my shirts with my pectorals. And my back pain is mostly gone after I focus on shoulder and lower back exercises.

New stress relievers

I used to go to the library to read. To unwind.

I used to go to the cinema to watch movies. To imagine.

Not anymore.

Now I better appreciate the times I do spend with my family and friends, ever since the lockdown eased up.

I hope you’re well wherever you are, whenever you are.

Learning Russian and Python

Russian grammar makes me want to throw my hands up in frustration and anger.

I’ve been learning Russian for over two years now.

I started by using Duolingo. I thought I was progressing quite nicely. But the gamified way of learning soon wore me down. And after a year and a half, I still could not come up with sentences of more than 5 words.

So I searched for a better way of learning. I found the apps Busuu and Lingvist to be helpful, especially Lingvist since it’s a spaced repetition app without me having to input my own words (like Anki. I’m lazy). I’ve started to actively read Russian articles (blogs or news) and watch Russian YouTube videos. And I’m using more time on the learning process, and my progress finally moved forward over the last few months.

In the midst of all that linguistic frustration, my work also involved reading and writing Python code. I had to deal with machine learning and AI and the new fangled new thing these days is Python and the powerful libraries that support it.

Let me tell you, the lack of an ending semicolon took me a while to get over.

And Python was just the tip of the iceberg. The latest technological tools and languages appear to move away from the “traditional” programming structures such as if statements and for loops. They still have them, but somehow presented in a different manner.

Python has the list comprehension thing (which looks like an SQL select statement to me). Scratch from MIT uses visual blocks to construct programming logic. And Tensorflow is … tense (tensors are hyperdimensional matrices?).

So my struggle with Russian is mostly with the 6 cases. The language makes differences for “for you” and “to you” as in <<??? ????>> and <<? ?????>>. The gender attachment to all objects didn’t help (I mean other languages such as German has it too but still).

And the newer programming languages or technologies seem to be encapsulating more and more constructs to work on a higher and more abstract level. It might even seem that programming languages are trying to approach how humans talk to each other.

And that might be the actual point. Communication.

We speak to each other and convey our ideas through natural languages. And we do the same “speaking” to computers through programming languages. The difference is that humans are more capable of picking up nuances and self-correct mistakes in communication.

Python pass by reference

Some time ago, I was given the opportunity to take a free course in Python. I was like “Sure why not? And it’s free? Woot!” (I don’t actually say “woot” but it seems like the kind of thing people say, right?)

The course is a beginner module meant for technical people (but not full-on coders). I was the only professional programmer in the class. I didn’t care, I don’t know Python. So 2 points of interest…

White space is critical

The programming languages I know consider white space as something to make the code easier to read for the human. Python elevates that to a whole new level.

I’m not even talking about the debate about whether a tab or 4 spaces is better for indentation. Python will punish you if you used 4 spaces for indentation here and then use 3 spaces for indentation there. This is especially terrible if you use an editor where a tab looks like 4 spaces so it looks like the indentation is fine but it’s not.

Parameter values are by default passed by reference

This one took a bit of getting used to. I’m used to passing values to functions and knowing that those values (or classes or structs) will never be tampered with unless I say so. For example, with the “ref” keyword in C#:

public void Foobar(ref ComplicatedClass ImComplex)
// ImComplex will possibly be modified

I’ll just slide that into my “good to know, but I’ll probably never use” list. I don’t want any weird errors slithering up because that’s hard to swallow. (I swear that’s the end of my snake jokes)

P.S. Happy Independence Day to you if you celebrate it. Coincidentally, it’s also the official day that my company closed. So Independence Day to me too.

Calming down

About 3 years ago, the stress was slowly killing me.

So back then I was working on my own business, using some of the money I earned as a software consultant, and running a company as the CEO/director. The consultancy job required me to travel an obscene distance taking an absurd amount of time to the tune of 4 to 4.5 hours every single day.

I slept an average of 4.5 hours a night. 6 if I’m lucky (such as weekends). My last thought before sleep was typically the injustice inflicted on me by my Troublesome Business Partner (TBP). My first thought upon waking up was that of TBP. My blood boiled continually throughout the day whenever the thought of TBP flits past my brain.

My health was a wreck. I could see my muscles wasted away. My breath was usually ragged and shallow. My back hurt and my shoulders ached.

Sometimes just standing still and doing nothing was the best thing I could do for myself. Because moving or even the thought of moving was too mentally painful.

I was continually worried about money. My company wasn’t making profits and I had to make payroll using my own personal money (because my business partners seemed to think it was unheard of for them to continue investing their money and time beyond the initial company setup).

The wakeup call

So one night I was walking home after work. It was near midnight when I alighted the train. The night was cool and I wanted to save money by not taking the bus.

I was enjoying the slight breeze and the solitude of the quiet night when I felt something. More precisely it was what I didn’t feel.

Because for a few moments I felt the absence of my heart beating.

I stood shivering on the walk path beside the road. Tears welled up. I was just so tired. I took long deep breaths as I watched the occasional car pass by. Then I continued my journey home.

You might think I imagined that. I thought so too. Until my heart “gave out” on a couple of occasions after the initial one. It was then that I finally came to terms that I had to do something drastic to turn my life around.

Because whatever I was doing was clearly not working.

The frantic search for relaxation

Prior to my heart incident, I was already trying my darndest to relax. I’m not stupid you know. So I followed the typical advice.

Such as long walks, preferably in nature. I took long walks in the nearby park. But the presence of humans agitated me more than the relaxation benefits. Yes people stress me out, like way more than was normal.

I wasn’t unfriendly nor anti-social. But after dealing with TBP, I became much more cynical and distrustful of people.

I did deep breathing, forcing my breaths into long drawn out streams of air flow. It sort of helped. But I was so wired up that the moment I stopped consciously breathing, my breathing adjusted to simulate a chihuahua panting. It was like two giant hands squeezing my chest and back together, holding with enough space that I could just barely breathe.

I also tried visualisation and meditation. Years ago I would have found it easy to maintain a light meditative state. That stressed out Vincent? Oh he was bombarded with a constant flow of anger, sadness, money worries, future worries, frustration, moments of small joy. I had a nervous tick in my left eyelid.

“What about pets?” Have I mention my cat died? A small part of me died too. I’ll leave it there…

“Well what about exercise?” I also did that. The thing was, you need to be able to recover from that exercise to reap the benefits. I was so stressed out that some pushups or jumping jacks took me days, maybe even a couple of weeks for me to recover. I was so worn out.

“Uh massage?” I couldn’t afford it.

“Talk to friends?” They’re not the business kind of people. And even if it’s just to talk it out, they’re guys. It’s not a manly thing to talk about such woes. So I just hang out with my friends but I kept my troubles to myself.

I was at my wit’s end. But what I’ve told you were what I actively did for relaxing. Mentally with meditation. Physically with exercise. Emotionally and socially with friends.

Those helped, but not significantly enough to turn things around for me. I needed something more drastic. Something that is done to me. Something that is passive for me once I start the initial process.

Next time I’ll tell you about my research into health and fitness and the ridiculous amount of health supplements I tried.