Jul 15, 2020

Creating an angular service to share data between components using session storage

Create the session storage service as:
import { Injectable, OnDestroy, OnInit } from "@angular/core";
import { ReplaySubject } from "rxjs";
import { environment } from "../../../environments/environment";
@Injectable({
providedIn: "root",
})
export class StorageService implements OnInit, OnDestroy {
private storageChange$: ReplaySubject<{
key: string;
value: string;
}> = new ReplaySubject();
constructor() {}
ngOnInit() {
sessionStorage.clear();
localStorage.clear();
}
ngOnDestroy() {
this.storageChange$.unsubscribe();
}
public store(key: string, data: any): void {
// log in console for each store method call. In development mode only
if (environment.production === false) {
console.log("StorageService.store():", key, sessionStorage);
}
sessionStorage.setItem(key, JSON.stringify(data));
this.storageChange$.next({ key: key, value: JSON.stringify(data) });
}
public get() {
// log in console if key exists in data store. In development mode only
if (environment.production === false) {
console.log("StorageService.get()", sessionStorage);
}
//window[area].getItem(key);
return this.storageChange$;
}
}


To store and retrieve the session storage data, use the service as:
// to store data
this._storageService.store(
key, // as string
object // any object to store
);
// to retrieve data
this._storageService
.get()
.pipe(
filter(({ key }) => key === KEY_AS_STRING),
map((data) => {
return JSON.parse(data.value) as Object;
})
)
.subscribe((data) => {
// use data
});


Creating an angular service to share data between components

Create a Data store to save data as key and values. E.g:
export class DataStore {
private map = new Map<string, any>();
add(key: string, value: any) {
this.map.set(key, value);
}
hasKey(key: string) {
return this.map.has(key);
}
getValue(key: string) {
return this.map.get(key);
}
remove(key: string) {
if (this.hasKey(key)) {
this.map.delete(key);
return true;
} else {
return false;
}
}
}
view raw DataStore.ts hosted with ❤ by GitHub


Note: It uses build in Map data structure and it already has function to add, remove, delete and check objects.

Now let's create a service.
import { Injectable } from "@angular/core";
import { Subject, Observable } from "rxjs";
import { DataStore } from "../models/datastore.model";
import { environment } from "../../../environments/environment";
@Injectable({
providedIn: "root",
})
export class StorageService {
private _dataStore = new DataStore();
private readonly changes = new Subject<DataStore>();
constructor() {}
public get(): Observable<DataStore> {
// log in console if key exists in data store. In development mode only
if (environment.production === false) {
console.log("StorageService.get()", this._dataStore);
}
return this.changes.asObservable();
}
public store(key: string, data: any): void {
// check if object already exist in data store and remove it
if (this._dataStore.hasKey(key)) {
this._dataStore.remove(key);
}
this._dataStore.add(key, data);
this.changes.next(this._dataStore);
// log in console for each store method call. In development mode only
if (environment.production === false) {
console.log("StorageService.store() : DataStore:", key, this._dataStore);
}
}
public remove(key) {
// log in console if key exists in data store. In development mode only
if (environment.production === false) {
console.log(
"StorageService.remove() : DataStore has key:",
this._dataStore.hasKey(key)
);
}
if (this._dataStore.hasKey(key)) {
this._dataStore.remove(key);
this.changes.next(this._dataStore);
}
}
}


To store and save data call the service as:
// to store data
this._dataStorageService.store(
key, // string
object //any item
);
// to retrieve data, can be used any component
this._dataStorageService.get().subscribe((data) => {
console.log(data);
});


May 22, 2020

Using C# to read an update excel files

Create a new solution and add the DocumentFormat.OpenXml Nuget packages to this solution.

Add a new class ExcelManager.cs with the following code:


using System;
using System.Collections.Generic;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.IO;
using Logger;
using DocumentFormat.OpenXml;

namespace Demo
{
    class ExcelManager : IDisposable
    {
        #region Private Variables
        SpreadsheetDocument _document;
        Sheet _sheet;
        Worksheet _worksheet;
        #endregion

        #region Public Properties
        public IEnumerable<Row> Rows { get; private set; }
        #endregion

        #region Constructor
        public ExcelManager(string filePath)
        {
            if(!File.Exists(filePath))
            {
                Logger.log.Error($"Error in DataManager(). File with the following path does not exists:{filePath}");
                return;
            }
            else
            {
                Logger.log.Info($"Processing file at path: {filePath}");
                //Open the Excel file in Edit Mode using OpenXml.
                _document = SpreadsheetDocument.Open(filePath, true);
                _sheet = _document.WorkbookPart.Workbook.Sheets.GetFirstChild<Sheet>();
                _worksheet = (_document.WorkbookPart.GetPartById(_sheet.Id.Value) as WorksheetPart).Worksheet;
                Rows = _worksheet.GetFirstChild<SheetData>().Descendants<Row>();
            }
        }
        #endregion

        public void Dispose()
        {
            _document.Dispose();
            _document = null;
            _sheet = null;
            _worksheet = null;
        }

        #region Public Excel Functions
        public string GetCellValue(Cell cell)
        {
            return _document.WorkbookPart.SharedStringTablePart.SharedStringTable.Elements<SharedStringItem>().ElementAt(Convert.ToInt32(cell.InnerText)).InnerText;
        }

        public string GetCellValueByReference(string cellReference)
        {
            var cell = _worksheet.Descendants<Cell>().Where(c => c.CellReference == cellReference).FirstOrDefault();

            if (cell != null)
            {
                return GetCellValue(cell);
            }
            else
            {
                return null;
            }
        }

        public void UpdateCell(string columnName, uint rowIndex, string value)
        {
            try
            {
                Cell cell = GetCellByColumnName(columnName, rowIndex);
                if (cell != null)
                {
                    cell.CellValue = new CellValue(value);
                    cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);

                    // Save the worksheet.
                    _worksheet.Save();
                }
                else
                {
                    Logger.log.Warn($"Error in DataManager.UpdateCell(). Error: Cell is null");
                }
            }
            catch (Exception ex)
            {
                Logger.log.Error($"Error in DataManager.UpdateCell().Error: {ex.Message} StackTrace:{ex.StackTrace}");
            }
        }
        #endregion

        #region Private Excel functions
        private Cell GetCellByColumnName(string columnName, uint rowIndex)
        {
            Row row = GetRow(rowIndex);

            if (row == null)
                return null;

            string cellReference = GetColumnReference(columnName).FirstOrDefault().ToString();

            if (cellReference == null)
            { 
                Logger.log.Warn($"Error in DataManager.GetCellByColumnName(). Error: Cell Reference is null");
                return null;
            }
            else
                return row.Elements<Cell>().Where(c => string.Compare(c.CellReference.Value, cellReference + (rowIndex + 1), true) == 0).First();
        }

        private string GetColumnReference(string columnName)
        {
            var cell = GetRow(0).Elements<Cell>().FirstOrDefault(c => GetCellValue(c) == columnName);

            if (cell == null)
            {
                Logger.log.Warn($"Error in DataManager.GetColumnReference(). Error: Cannot retrieve cell with column name: {columnName}");
                return null;
            }
            else
                return cell.CellReference.Value;
        }

        private Row GetRow(uint rowIndex)
        {
            return Rows.ElementAt(int.Parse(rowIndex.ToString()));
        }
        #endregion
    }
}


This provides the basic items like rows of excel data and functions to save text based on column header names and retrieve cell values.

To add logging, refer to my blog here.