Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pu/issue617 #619

Merged
merged 18 commits into from
Apr 14, 2021
Merged

Pu/issue617 #619

merged 18 commits into from
Apr 14, 2021

Conversation

izulin
Copy link
Collaborator

@izulin izulin commented Mar 29, 2021

Context

Makes it so raw value used for initialization is stored together with parsed value in the graph.
Raw value is produced when engine is asked for serialization.
Fixes issue #617 by making it so ' is not dropped when provided as an input to the engine.

How has this been tested?

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature or improvement (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Additional language file or change to the existing one (translations)

Related issue(s):

  1. Unwanted string slice when cell value starts with ' #617

Checklist:

  • My code follows the code style of this project,
  • My change requires a change to the documentation,
  • I described the modification in the CHANGELOG.md file.

@izulin izulin requested a review from rsify March 29, 2021 16:01
@codecov
Copy link

codecov bot commented Mar 29, 2021

Codecov Report

Merging #619 (cebeeca) into develop (82c0053) will increase coverage by 0.00%.
The diff coverage is 91.66%.

Impacted file tree graph

@@           Coverage Diff            @@
##           develop     #619   +/-   ##
========================================
  Coverage    92.45%   92.45%           
========================================
  Files          164      164           
  Lines        38428    38460   +32     
  Branches      5330     5337    +7     
========================================
+ Hits         35527    35559   +32     
  Misses        2864     2864           
  Partials        37       37           
Impacted Files Coverage Δ
src/CellContentParser.ts 67.75% <0.00%> (+0.73%) ⬆️
src/GraphBuilder.ts 77.50% <25.00%> (ø)
src/Operations.ts 91.15% <90.90%> (ø)
...c/DependencyGraph/AddressMapping/AddressMapping.ts 82.03% <92.30%> (+0.59%) ⬆️
src/DependencyGraph/ValueCellVertex.ts 95.45% <94.73%> (-4.55%) ⬇️
src/ClipboardOperations.ts 93.75% <100.00%> (+0.08%) ⬆️
src/DependencyGraph/DependencyGraph.ts 85.72% <100.00%> (+0.07%) ⬆️
src/DependencyGraph/MatrixVertex.ts 94.63% <100.00%> (+0.18%) ⬆️
src/HyperFormula.ts 99.00% <100.00%> (ø)
src/Serialization.ts 94.63% <100.00%> (+0.71%) ⬆️

rsify
rsify previously approved these changes Mar 30, 2021
rsify added a commit to handsontable/handsontable that referenced this pull request Mar 30, 2021
as per the `.tgz` filename change, updates hyperformula to the version
from this PR: handsontable/hyperformula#619
test/interpreter/function-lcm.spec.ts Outdated Show resolved Hide resolved
test/interpreter/function-multinomial.spec.ts Outdated Show resolved Hide resolved
test/interpreter/function-gcd.spec.ts Outdated Show resolved Hide resolved
test/interpreter/operator-plus.spec.ts Outdated Show resolved Hide resolved
test/escaping-support.spec.ts Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
test/interpreter/criterion-computations.spec.ts Outdated Show resolved Hide resolved
@izulin
Copy link
Collaborator Author

izulin commented Mar 31, 2021

@wojciechczerniak

When you type into cell '4 in XL/GS, ' is stripped at the level of UI. Excel engine does not receive ', it just marks the cell somehow. In our case (see linked issue):
when cell is set value with ', we have to store this value in the cell, so when asked for the value we return correct value.
Thus when cell is assigned '4, it's value is the string not the number, and the string is "'4".

test/escaping-support.spec.ts Outdated Show resolved Hide resolved
@wojciechczerniak
Copy link
Contributor

When you type into cell '4 in XL/GS, ' is stripped at the level of UI. Excel engine does not receive ', it just marks the cell somehow. In our case (see linked issue):

@izulin Same with date format, currency or percent sign, yet, we keep them. HyperFormula does not have UI, exported content from the Excel should be correctly calculated without altering the data and serialized without loosing any parts of it.

And it's not stripped, Excel keeps the info and it will be shown in the formula bar as the cell content:
Screenshot 2021-03-31 at 14 52 28
Same for Google Sheets.

@izulin
Copy link
Collaborator Author

izulin commented Mar 31, 2021

When you type into cell '4 in XL/GS, ' is stripped at the level of UI. Excel engine does not receive ', it just marks the cell somehow. In our case (see linked issue):

@izulin Same with date format, currency or percent sign, yet, we keep them. HyperFormula does not have UI, exported content from the Excel should be correctly calculated without altering the data and serialized without loosing any parts of it.

And it's not stripped, Excel keeps the info and it will be shown in the formula bar as the cell content:
Screenshot 2021-03-31 at 14 52 28
Same for Google Sheets.

Try accessing the cell value, e.g. type 'abcd and do a concatenation on it, or indexing it.

@izulin
Copy link
Collaborator Author

izulin commented Mar 31, 2021

Try accessing the cell value, e.g. type 'abcd and do a concatenation on it, or indexing it.

Screenshot 2021-03-31 at 15 16 53

Screenshot 2021-03-31 at 15 17 04

Screenshot 2021-03-31 at 15 17 16

@wojciechczerniak
Copy link
Contributor

Try accessing the cell value, e.g. type 'abcd and do a concatenation on it, or indexing it.

Screenshot 2021-03-31 at 15 16 53 Screenshot 2021-03-31 at 15 17 04 Screenshot 2021-03-31 at 15 17 16

So? getCellValue strips the ' for calculations / coercing to text. =getCellValue(A1) & getCellValue(B1).

This is exactly what we need. For rendering the cell we call getCellValue and want it without the escape character.

BUT when we ask for the source with getCellSerialized it should be still there because it is the source data.

@rsify rsify dismissed their stale review April 1, 2021 11:25

leading ' should probably also get omitted when referencing the cell in a formula

jest.config.js Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
@izulin
Copy link
Collaborator Author

izulin commented Apr 3, 2021

@wojciechczerniak Ok, lets see how you like this approach.

Copy link
Contributor

@wojciechczerniak wojciechczerniak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The outcome is what we're looking for. But maybe it would be more useful to have internal getSerializedValue or getRawValue method instead literal arg?

I think we should look at serialization again. It does not work as intended. With getSheetSerialized I should be able to store and recreate the engine.

Consider an example:

  • User loads the app: initialize engine with data from server
  • User logs out / saves data: send getAllSheetsSerialized to server and store in databse / file
  • User logs in again, reinitialize the engine with data from server
  • Data was lost in the process 💣 💥
it('should not loose sheet information on serialziation', () => {
    const engine1 = HyperFormula.buildFromArray([
      [1, '2', 'foo', true, '\'1', '33$', '12/01/15']
    ])


    expect(engine1.getCellSerialized(adr('A1'))).toEqual(1)
    expect(engine1.getCellValueFormat(adr('A1'))).toEqual(undefined)
    expect(engine1.getCellValueDetailedType(adr('A1'))).toEqual(CellValueDetailedType.NUMBER_RAW)

    expect(engine1.getCellSerialized(adr('B1'))).toEqual(2)
    expect(engine1.getCellValueFormat(adr('B1'))).toEqual(undefined)
    expect(engine1.getCellValueDetailedType(adr('B1'))).toEqual(CellValueDetailedType.NUMBER_RAW)

    expect(engine1.getCellSerialized(adr('C1'))).toEqual('foo')
    expect(engine1.getCellValueFormat(adr('C1'))).toEqual(undefined)
    expect(engine1.getCellValueDetailedType(adr('C1'))).toEqual(CellValueDetailedType.STRING)

    expect(engine1.getCellSerialized(adr('D1'))).toEqual(true)
    expect(engine1.getCellValueFormat(adr('D1'))).toEqual(undefined)
    expect(engine1.getCellValueDetailedType(adr('D1'))).toEqual(CellValueDetailedType.BOOLEAN)

    expect(engine1.getCellSerialized(adr('E1'))).toEqual('\'1')
    expect(engine1.getCellValueFormat(adr('E1'))).toEqual(undefined)
    expect(engine1.getCellValueDetailedType(adr('E1'))).toEqual(CellValueDetailedType.STRING)

    expect(engine1.getCellSerialized(adr('F1'))).toEqual(33)
    expect(engine1.getCellValueFormat(adr('F1'))).toEqual('$')
    expect(engine1.getCellValueDetailedType(adr('F1'))).toEqual(CellValueDetailedType.NUMBER_CURRENCY)

    expect(engine1.getCellSerialized(adr('G1'))).toEqual(42016)
    expect(engine1.getCellValueFormat(adr('G1'))).toEqual(undefined)
    expect(engine1.getCellValueDetailedType(adr('G1'))).toEqual(CellValueDetailedType.NUMBER_DATE)

    // serialize and "send" data to server
    const serialized = engine1.getAllSheetsSerialized();

    // reload data and "restore" the previous state
    const engine2 = HyperFormula.buildFromSheets(serialized)

    expect(engine2.getCellSerialized(adr('A1'))).toEqual(1)
    expect(engine2.getCellValueFormat(adr('A1'))).toEqual(undefined)
    expect(engine2.getCellValueDetailedType(adr('A1'))).toEqual(CellValueDetailedType.NUMBER_RAW)

    expect(engine2.getCellSerialized(adr('B1'))).toEqual(2)
    expect(engine2.getCellValueFormat(adr('B1'))).toEqual(undefined)
    expect(engine2.getCellValueDetailedType(adr('B1'))).toEqual(CellValueDetailedType.NUMBER_RAW)

    expect(engine2.getCellSerialized(adr('C1'))).toEqual('foo')
    expect(engine2.getCellValueFormat(adr('C1'))).toEqual(undefined)
    expect(engine2.getCellValueDetailedType(adr('C1'))).toEqual(CellValueDetailedType.STRING)

    expect(engine2.getCellSerialized(adr('D1'))).toEqual(true)
    expect(engine2.getCellValueFormat(adr('D1'))).toEqual(undefined)
    expect(engine2.getCellValueDetailedType(adr('D1'))).toEqual(CellValueDetailedType.BOOLEAN)

    expect(engine2.getCellSerialized(adr('E1'))).toEqual('\'1')
    expect(engine2.getCellValueFormat(adr('E1'))).toEqual(undefined)
    expect(engine2.getCellValueDetailedType(adr('E1'))).toEqual(CellValueDetailedType.STRING)

    expect(engine2.getCellSerialized(adr('F1'))).toEqual(33)
    expect(engine2.getCellValueFormat(adr('F1'))).toEqual('$')
    expect(engine2.getCellValueDetailedType(adr('F1'))).toEqual(CellValueDetailedType.NUMBER_CURRENCY)

    expect(engine2.getCellSerialized(adr('G1'))).toEqual(42016)
    expect(engine2.getCellValueFormat(adr('G1'))).toEqual(undefined)
    expect(engine2.getCellValueDetailedType(adr('G1'))).toEqual(CellValueDetailedType.NUMBER_DATE)
  })

BTW. does the getCellValueFormat work for NUMBER_DATE?


I think that we should a better serialization approach for all the value types, not only the escaped string

@wojciechczerniak
Copy link
Contributor

Don't get me wrong! This is a good solution for the issue at hand. But I think we're going in the wrong direction overall and we will create a technical debt while we can introduce getSerializedValue at cell vertex and handle all types together instead a single if condition for escaped string. WDYT?

@izulin
Copy link
Collaborator Author

izulin commented Apr 7, 2021

Don't get me wrong! This is a good solution for the issue at hand. But I think we're going in the wrong direction overall and we will create a technical debt while we can introduce getSerializedValue at cell vertex and handle all types together instead a single if condition for escaped string. WDYT?

Good catch.

I agree this should be handled in a more integrated form.

@izulin
Copy link
Collaborator Author

izulin commented Apr 8, 2021

@wojciechczerniak This actually induced a larger refactor (yay CRUDS, yay Matrices!)

@lgtm-com
Copy link
Contributor

lgtm-com bot commented Apr 8, 2021

This pull request introduces 6 alerts when merging 706ae9c into e6cf049 - view on LGTM.com

new alerts:

  • 6 for Unused variable, import, function or class

CHANGELOG.md Outdated Show resolved Hide resolved
@izulin izulin requested a review from voodoo11 April 8, 2021 18:50
@lgtm-com
Copy link
Contributor

lgtm-com bot commented Apr 8, 2021

This pull request introduces 6 alerts when merging 45635e0 into e6cf049 - view on LGTM.com

new alerts:

  • 6 for Unused variable, import, function or class

@lgtm-com
Copy link
Contributor

lgtm-com bot commented Apr 9, 2021

This pull request introduces 6 alerts when merging a57488b into 82c0053 - view on LGTM.com

new alerts:

  • 6 for Unused variable, import, function or class

@izulin
Copy link
Collaborator Author

izulin commented Apr 12, 2021

Known issue: raw value is lost if the numeric input becomes part of a matrix.

@lgtm-com
Copy link
Contributor

lgtm-com bot commented Apr 12, 2021

This pull request introduces 8 alerts when merging ab20ae8 into 82c0053 - view on LGTM.com

new alerts:

  • 8 for Unused variable, import, function or class

Copy link
Contributor

@wojciechczerniak wojciechczerniak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! 🍻

Just few cosmetic questions if you don't mind

expect(engine1.getCellValueDetailedType(adr('F1'))).toEqual(CellValueDetailedType.NUMBER_CURRENCY)

expect(engine1.getCellSerialized(adr('G1'))).toEqual('12/01/15')
expect(engine1.getCellValueFormat(adr('G1'))).toEqual(undefined)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a note that this is wrong? With link to #626

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

riiiight

describe('serialization', () => {
it('should not loose sheet information on serialization', () => {
const engine1 = HyperFormula.buildFromArray([
[1, '2', 'foo', true, '\'1', '33$', '12/01/15']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add % and a literal error #DIV/0, =#CUSTOM! so we have the whole picture here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -643,7 +643,7 @@ export class HyperFormula implements TypedEmitter {
*
* @category Cells
*/
public getCellSerialized(cellAddress: SimpleCellAddress): NoErrorCellValue {
public getCellSerialized(cellAddress: SimpleCellAddress): RawCellContent {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider this as a breaking change to the public API? IMO yes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

@lgtm-com
Copy link
Contributor

lgtm-com bot commented Apr 14, 2021

This pull request introduces 8 alerts when merging cebeeca into 82c0053 - view on LGTM.com

new alerts:

  • 8 for Unused variable, import, function or class

Copy link
Contributor

@wojciechczerniak wojciechczerniak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@izulin izulin merged commit 67d5802 into develop Apr 14, 2021
@izulin izulin deleted the pu/issue617 branch April 14, 2021 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants