diff --git a/Codeunits/Cod81001.DETDataEditorMgt.al b/Codeunits/Cod81001.DETDataEditorMgt.al index 9cd4ae6..175a156 100644 --- a/Codeunits/Cod81001.DETDataEditorMgt.al +++ b/Codeunits/Cod81001.DETDataEditorMgt.al @@ -18,8 +18,11 @@ codeunit 81001 "DET Data Editor Mgt." procedure GetNewColumnValue(var RecRef: RecordRef; var FieldRefVar: FieldRef; var SourceRecordId: RecordId; var TempNameValueBuffer: Record "Name/Value Buffer" temporary): Boolean var FieldRec: Record Field; + DataEditorSetup: Record "DET Data Editor Setup"; EditValue: page "DET Edit Value"; NameValueLookup: Page "Name/Value Lookup"; + xRecRef: RecordRef; + xFieldRefVar: FieldRef; OptionValue: Text; ListOfOptions: List of [Text]; FieldNo: Integer; @@ -54,6 +57,8 @@ codeunit 81001 "DET Data Editor Mgt." end; if IsFieldIsPartOfPK(RecRef, FieldRefVar) then begin + xRecRef := RecRef.Duplicate(); + xFieldRefVar := RecRef.Field(FieldRefVar.Number()); if FieldRefVar.Type() = FieldRefVar.Type::Option then begin Evaluate(FieldNo, TempNameValueBuffer.Name); ResultVariant := FieldNo; @@ -63,6 +68,9 @@ codeunit 81001 "DET Data Editor Mgt." FieldRefVar.Value(TempNameValueBuffer.Value) else FieldRefVar.Value(format(ResultVariant)); + if DataEditorSetup.Get() then + if DataEditorSetup."Enable Data Editor Log" then + LogRename(RecRef.Number(), FieldRefVar.Number(), RecRef.RecordId(), xFieldRefVar, FieldRefVar, true); exit(true); end; FieldRefVar.Value(ResultVariant); @@ -89,13 +97,17 @@ codeunit 81001 "DET Data Editor Mgt." var SingleInstanceStorage: Codeunit "DET Single Instance Storage"; RecordRefTemp: RecordRef; + xRecRef: RecordRef; FieldRefVar2: FieldRef; + xFieldRefVar: FieldRef; KeyRefVar: KeyRef; KeyCount: Integer; DictOfFieldKeyType: Dictionary of [Integer, Text]; KeyValueIndexRelDict: Dictionary of [Integer, Text[2048]]; begin KeyRefVar := inRecRef.KeyIndex(1); + xRecRef := inRecRef.Duplicate(); + xFieldRefVar := xRecRef.Field(FieldRefVar.Number()); for KeyCount := 1 to KeyRefVar.FieldCount() do begin FieldRefVar2 := KeyRefVar.FieldIndex(KeyCount); if FieldRefVar2.Number() <> FieldRefVar.Number() then @@ -270,7 +282,316 @@ codeunit 81001 "DET Data Editor Mgt." SourceRecordId := inRecRef.RecordId(); end; + procedure ImportTable(WithValidation: Boolean) var - RenamePKNotSuppErr: Label 'Changing the primary key for >15 values is not supported.'; + TempBlob: Codeunit "Temp Blob"; + ImportExportDialog: Page "DET Import/Export Dialog"; + RecRef: RecordRef; + xRecRef: RecordRef; + FieldRef: FieldRef; + xFieldRef: FieldRef; + ImportOnFind: Enum "DET Import On Find"; + InStreamVar: InStream; + JObject: JsonObject; + JToken: JsonToken; + JTokenField: JsonToken; + JArray: JsonArray; + ListOfTables: List of [Text]; + ListOfFields: List of [Text]; + TableNoAsTxt, FieldNoAsTxt : Text; + TableNo, FieldNo : Integer; + Skipped, Inserted, Modified : Integer; + IsPKReady, IsRecordExist : Boolean; + ResultMsg: TextBuilder; + begin + ImportExportDialog.Caption('Import Dialog'); + if not (ImportExportDialog.RunModal() in [Action::OK, Action::LookupOK]) then + exit; + ImportOnFind := ImportExportDialog.GetImportOnFind(); + + TempBlob.CreateInStream(InStreamVar, TextEncoding::UTF8); + if not UploadIntoStream(JSONFilterLbl, InStreamVar) then + exit; + + JObject.ReadFrom(InStreamVar); + ListOfTables := JObject.Keys(); + foreach TableNoAsTxt in ListOfTables do begin + JObject.Get(TableNoAsTxt, JToken); + Evaluate(TableNo, TableNoAsTxt); + Clear(RecRef); + + RecRef.Open(TableNo); + RecRef.ReadIsolation := RecRef.ReadIsolation::ReadCommitted; + + xRecRef.Open(TableNo); + xRecRef.ReadIsolation := xRecRef.ReadIsolation::ReadCommitted; + + JArray := JToken.AsArray(); + + foreach JToken in JArray do begin + RecRef.Init(); + ListOfFields := JToken.AsObject().Keys(); + + foreach FieldNoAsTxt in ListOfFields do begin + JToken.AsObject().Get(FieldNoAsTxt, JTokenField); + Evaluate(FieldNo, FieldNoAsTxt); + FieldRef := RecRef.Field(FieldNo); + + if not IsPKReady then + if not IsFieldIsPartOfPK(RecRef, FieldRef) then begin + IsRecordExist := xRecRef.Get(RecRef.RecordId()); + IsPKReady := true; + end; + + if IsRecordExist then + xFieldRef := xRecRef.Field(FieldNo); + + FieldRef.Value(TextValueAsVariant(FieldRef.Type, CopyStr(JTokenField.AsValue().AsText(), 1, 2048))); + if WithValidation then + FieldRef.Validate(); + + if IsRecordExist and (ImportOnFind = ImportOnFind::Modify) then + LogModify(RecRef.Number(), FieldNo, RecRef.RecordId(), xFieldRef, FieldRef, WithValidation); + end; + + case ImportOnFind of + ImportOnFind::Error: + begin + RecRef.Insert(WithValidation); + LogInsert(RecRef.Number(), RecRef.RecordId(), WithValidation); + Inserted += 1; + end; + ImportOnFind::Skip: + if RecRef.Insert(WithValidation) then begin + LogInsert(RecRef.Number(), RecRef.RecordId(), WithValidation); + Inserted += 1; + end else + Skipped += 1; + ImportOnFind::Modify: + if RecRef.Insert(WithValidation) then begin + LogInsert(RecRef.Number(), RecRef.RecordId(), WithValidation); + Inserted += 1; + end else begin + RecRef.Modify(WithValidation); + Modified += 1; + end; + end; + + end; + RecRef.Close(); + end; + ResultMsg.AppendLine(ImportFinishedLbl); + ResultMsg.AppendLine(StrSubstNo(InsertedLbl, Inserted)); + ResultMsg.AppendLine(StrSubstNo(ModifiedLbl, Modified)); + ResultMsg.AppendLine(StrSubstNo(SkippedLbl, Skipped)); + + if GuiAllowed() then + Message(ResultMsg.ToText()); + end; + + procedure ExportTable(var DataEditorBuffer: Record "DET Data Editor Buffer"; FieldIdsToExport: List of [Integer]) + var + TempBlob: Codeunit "Temp Blob"; + RecRef: RecordRef; + JArray: JsonArray; + JObjectRoot: JsonObject; + InStreamVar: InStream; + OutStreamVar: OutStream; + FileName: Text; + begin + if DataEditorBuffer.IsEmpty() then + exit; + + if DataEditorBuffer.FindSet() then begin + RecRef.Open(DataEditorBuffer."Source Record ID".TableNo()); + RecRef.ReadIsolation := RecRef.ReadIsolation::ReadCommitted; + repeat + RecRef.Get(DataEditorBuffer."Source Record ID"); + JArray.Add(CreateJSONObjectFromRecord(RecRef, FieldIdsToExport)); + until DataEditorBuffer.Next() = 0; + end; + + JObjectRoot.Add(Format(RecRef.Number()), JArray); + + FileName := StrSubstNo(FileNameLbl, RecRef.Caption(), Format(CurrentDateTime, 0, '--_..'), 'json'); + + RecRef.Close(); + + TempBlob.CreateInStream(InStreamVar, TextEncoding::UTF8); + TempBlob.CreateOutStream(OutStreamVar, TextEncoding::UTF8); + JObjectRoot.WriteTo(OutStreamVar); + DownloadFromStream(InStreamVar, '', '', '', FileName); + end; + + local procedure CreateJSONObjectFromRecord(RecRef: RecordRef; FieldIdsToExport: List of [Integer]) JObject: JsonObject + var + FieldRefVar: FieldRef; + BooleanValue: Boolean; + i: Integer; + begin + for i := 1 to RecRef.FieldCount() do begin + FieldRefVar := RecRef.FieldIndex(i); + if FieldIdsToExport.Contains(FieldRefVar.Number()) then + if (FieldRefVar.Class = FieldClass::Normal) and not (FieldRefVar.Type in [FieldType::Blob, FieldType::Media, FieldType::MediaSet]) then + case FieldRefVar.Type() of + FieldRefVar.Type::Option: + JObject.Add(Format(FieldRefVar.Number()), FieldRefVar.OptionMembers.Split(',').IndexOf(FieldRefVar.Value) - 1); + FieldRefVar.Type::Boolean: + begin + Evaluate(BooleanValue, format(FieldRefVar.Value, 0, 9)); + JObject.Add(Format(FieldRefVar.Number()), BooleanValue); + end; + else + JObject.Add(Format(FieldRefVar.Number()), Format(FieldRefVar.Value)); + end; + end; + end; + + procedure LogInsert(TableNo: Integer; SourceRecordId: RecordId; WithValidation: Boolean) + var + OldValue: FieldRef; + NewValue: FieldRef; + begin + Log(Enum::"DET Log Action Type"::Insert, SourceRecordId, TableNo, 0, OldValue, NewValue, WithValidation, false); + end; + + procedure LogDelete(TableNo: Integer; SourceRecordId: RecordId; WithValidation: Boolean) + var + OldValue: FieldRef; + NewValue: FieldRef; + begin + Log(Enum::"DET Log Action Type"::Delete, SourceRecordId, TableNo, 0, OldValue, NewValue, WithValidation, false); + end; + + procedure LogModify(TableNo: Integer; FieldNo: Integer; SourceRecordId: RecordId; OldValue: FieldRef; NewValue: FieldRef; WithValidation: Boolean) + begin + Log(Enum::"DET Log Action Type"::Modify, SourceRecordId, TableNo, FieldNo, OldValue, NewValue, WithValidation, true); + end; + + procedure LogRename(TableNo: Integer; FieldNo: Integer; SourceRecordId: RecordId; OldValue: FieldRef; NewValue: FieldRef; WithValidation: Boolean) + begin + Log(Enum::"DET Log Action Type"::Rename, SourceRecordId, TableNo, FieldNo, OldValue, NewValue, WithValidation, true); + end; + + procedure Log(ActionType: Enum "DET Log Action Type"; SourceRecordId: RecordId; TableNo: Integer; FieldNo: Integer; OldValue: FieldRef; NewValue: FieldRef; WithValidation: Boolean; HasValues: Boolean) + var + DataEditorLog: Record "DET Data Editor Log"; + begin + if HasValues then begin + if (OldValue.Class() = FieldClass::FlowField) or (OldValue.Type() = FieldType::Blob) then + OldValue.CalcField(); + if (NewValue.Class() = FieldClass::FlowField) or (NewValue.Type() = FieldType::Blob) then + NewValue.CalcField(); + end; + + if not NumberSequence.Exists(LogNumberSequenceLbl) then + NumberSequence.Insert(LogNumberSequenceLbl); + + DataEditorLog.Init(); + DataEditorLog."Entry No." := NumberSequence.Next(LogNumberSequenceLbl); + DataEditorLog."Action Type" := ActionType; + DataEditorLog."Record Id" := SourceRecordId; + DataEditorLog."Table No." := TableNo; + DataEditorLog."Field No." := FieldNo; + DataEditorLog."With Validation" := WithValidation; + if HasValues then begin + DataEditorLog."New Value" := CopyStr(Format(NewValue.Value()), 1, MaxStrLen(DataEditorLog."New Value")); + DataEditorLog."Old Value" := CopyStr(Format(OldValue.Value()), 1, MaxStrLen(DataEditorLog."Old Value")); + end; + DataEditorLog.Insert(true); + + if not HasValues then + exit; + + if OldValue.Type() = FieldType::Blob then + DataEditorLog."Old Value BLOB" := OldValue.Value() + else + DataEditorLog.SetBLOBTextData(DataEditorLog.FieldNo("Old Value BLOB"), Format(OldValue.Value()), TextEncoding::UTF8); + + if NewValue.Type() = FieldType::Blob then + DataEditorLog."New Value BLOB" := NewValue.Value() + else + DataEditorLog.SetBLOBTextData(DataEditorLog.FieldNo("New Value BLOB"), Format(NewValue.Value()), TextEncoding::UTF8); + end; + + procedure TextValueAsVariant(FieldTypeVar: FieldType; ValueAsText: Text[2048]): Variant + var + DateFormulaValue: DateFormula; + IntegerValue: Integer; + DecimalValue: Decimal; + BooleanValue: Boolean; + DateValue: Date; + DateTimeValue: DateTime; + TimeValue: Time; + GuidValue: Guid; + BigIntegerValue: BigInteger; + begin + case FieldTypeVar of + FieldTypeVar::Code, FieldTypeVar::Text: + exit(ValueAsText); + FieldTypeVar::Integer: + begin + Evaluate(IntegerValue, ValueAsText); + exit(IntegerValue); + end; + FieldTypeVar::Decimal: + begin + Evaluate(DecimalValue, ValueAsText); + exit(DecimalValue); + end; + FieldTypeVar::Boolean: + begin + Evaluate(BooleanValue, ValueAsText); + exit(BooleanValue); + end; + FieldTypeVar::Date: + begin + Evaluate(DateValue, ValueAsText); + exit(DateValue); + end; + FieldTypeVar::DateFormula: + begin + Evaluate(DateFormulaValue, ValueAsText); + exit(DateFormulaValue); + end; + FieldTypeVar::DateTime: + begin + Evaluate(DateTimeValue, ValueAsText); + exit(DateTimeValue); + end; + FieldTypeVar::Time: + begin + Evaluate(TimeValue, ValueAsText); + exit(TimeValue); + end; + FieldTypeVar::Guid: + begin + Evaluate(GuidValue, ValueAsText); + exit(GuidValue); + end; + FieldTypeVar::BigInteger: + begin + Evaluate(BigIntegerValue, ValueAsText); + exit(BigIntegerValue); + end; + FieldTypeVar::Option: + begin + Evaluate(IntegerValue, ValueAsText); + exit(IntegerValue); + end; + else + exit(ValueAsText); + end; + end; + + var + RenamePKNotSuppErr: Label 'Changing the primary key for >15 values is not supported.'; + ImportFinishedLbl: Label 'Import is finished.'; + InsertedLbl: Label 'Inserted: %1', Comment = '%1 = Inserted record count'; + ModifiedLbl: Label 'Modified: %1', Comment = '%1 = Modified record count'; + SkippedLbl: Label 'Skipped: %1', Comment = '%1 = Skipped record count'; + LogNumberSequenceLbl: Label 'DETNSqwerty', Locked = true; + FileNameLbl: Label '%1_%2.%3', Locked = true; + JSONFilterLbl: Label 'JSON files (*.json, *.txt)|*.json;*.txt', Locked = true; } \ No newline at end of file diff --git a/Enums/Enum81000.DETLogActionType.al b/Enums/Enum81000.DETLogActionType.al new file mode 100644 index 0000000..6594217 --- /dev/null +++ b/Enums/Enum81000.DETLogActionType.al @@ -0,0 +1,25 @@ +enum 81000 "DET Log Action Type" +{ + Extensible = true; + + value(0; " ") + { + Caption = ' '; + } + value(1; Insert) + { + Caption = 'Insert'; + } + value(2; "Modify") + { + Caption = 'Modify'; + } + value(3; Delete) + { + Caption = 'Delete'; + } + value(4; Rename) + { + Caption = 'Rename'; + } +} diff --git a/Enums/Enum81001.DETImportOnFind.al b/Enums/Enum81001.DETImportOnFind.al new file mode 100644 index 0000000..12bf1ad --- /dev/null +++ b/Enums/Enum81001.DETImportOnFind.al @@ -0,0 +1,17 @@ +enum 81001 "DET Import On Find" +{ + Extensible = true; + + value(0; Error) + { + Caption = 'Error'; + } + value(1; "Modify") + { + Caption = 'Modify'; + } + value(2; Skip) + { + Caption = 'Skip'; + } +} diff --git a/Pages/Pag81000.DETDataEditorBuffer.al b/Pages/Pag81000.DETDataEditorBuffer.al index 4deb13d..a7551a9 100644 --- a/Pages/Pag81000.DETDataEditorBuffer.al +++ b/Pages/Pag81000.DETDataEditorBuffer.al @@ -6414,16 +6414,51 @@ page 81000 "DET Data Editor Buffer" } actions { + area(Promoted) + { + actionref(InsertNew_promoted; InsertNew) + { + + } + actionref("DET Delete Selected_Promoted"; "DET Delete Selected") + { + + } + actionref("DET Update Column_promoted"; "DET Update Column") + { + + } + actionref("DET Copy Column To Column_promoted"; "DET Copy Column To Column") + { + + } + actionref("DET Sort_promoted"; "DET Sort") + { + + } + actionref("DET Find & Replace_promoted"; "DET Find & Replace") + { + + } + actionref(Refresh_promoted; Refresh) + { + + } + actionref(ExportTableData_promoted; ExportTableData) + { + + } + actionref(ImportTableData_promoted; ImportTableData) + { + + } + } area(Processing) { action(InsertNew) { ApplicationArea = All; Image = Add; - Promoted = true; - PromotedIsBig = true; - PromotedCategory = Process; - PromotedOnly = true; Caption = 'Insert new record'; ToolTip = 'Insert new record'; trigger OnAction() @@ -6435,12 +6470,9 @@ page 81000 "DET Data Editor Buffer" { ApplicationArea = All; Image = Delete; - Promoted = true; - PromotedIsBig = true; - PromotedCategory = Process; - PromotedOnly = true; Caption = 'Delete Selected'; ToolTip = 'Delete Selected'; + Visible = false;// TODO: Do we really need this? trigger OnAction() var DataEditorBuffer: Record "DET Data Editor Buffer"; @@ -6460,10 +6492,6 @@ page 81000 "DET Data Editor Buffer" { ApplicationArea = All; Image = Column; - Promoted = true; - PromotedIsBig = true; - PromotedCategory = Process; - PromotedOnly = true; Caption = 'Update Column'; ToolTip = 'Update Column'; trigger OnAction() @@ -6475,10 +6503,6 @@ page 81000 "DET Data Editor Buffer" { ApplicationArea = All; Image = Column; - Promoted = true; - PromotedIsBig = true; - PromotedCategory = Process; - PromotedOnly = true; Caption = 'Copy Column To Column'; ToolTip = 'Copy Column To Column'; trigger OnAction() @@ -6490,10 +6514,6 @@ page 81000 "DET Data Editor Buffer" { ApplicationArea = All; Image = SortAscending; - Promoted = true; - PromotedIsBig = true; - PromotedCategory = Process; - PromotedOnly = true; Caption = 'Sort'; ToolTip = 'Sort'; trigger OnAction() @@ -6505,10 +6525,6 @@ page 81000 "DET Data Editor Buffer" { ApplicationArea = All; Image = Find; - Promoted = true; - PromotedIsBig = true; - PromotedCategory = Process; - PromotedOnly = true; Caption = 'Find & Replace'; ToolTip = 'Find & Replace'; trigger OnAction() @@ -6520,10 +6536,6 @@ page 81000 "DET Data Editor Buffer" { ApplicationArea = All; Image = Refresh; - Promoted = true; - PromotedIsBig = true; - PromotedCategory = Process; - PromotedOnly = true; Caption = 'Refresh'; ToolTip = 'Refresh this page with current filters'; @@ -6532,6 +6544,28 @@ page 81000 "DET Data Editor Buffer" LoadData(); end; } + action(ExportTableData) + { + ApplicationArea = All; + Caption = 'Export Table Data'; + ToolTip = 'Export Table Data, only loaded fields will be exported.'; + Image = ExportDatabase; + trigger OnAction() + begin + ExportTable(); + end; + } + action(ImportTableData) + { + ApplicationArea = All; + Caption = 'Import Table Data'; + ToolTip = 'Import Table Data, depends on previously selected validation.'; + Image = ImportDatabase; + trigger OnAction() + begin + ImportTable(); + end; + } } } @@ -6540,6 +6574,21 @@ page 81000 "DET Data Editor Buffer" DeleteSourceRecord(Rec."Source Record ID"); end; + local procedure ExportTable() + var + DataEditorMgt: Codeunit "DET Data Editor Mgt."; + begin + DataEditorMgt.ExportTable(Rec, LoadFieldNoList); + end; + + local procedure ImportTable() + var + DataEditorMgt: Codeunit "DET Data Editor Mgt."; + begin + DataEditorMgt.ImportTable(not WithoutValidate); + LoadData(); + end; + local procedure FindAndReplace() var FindAndReplacePage: Page "DET Find and Replace"; @@ -6556,8 +6605,10 @@ page 81000 "DET Data Editor Buffer" DataEditorMgt: Codeunit "DET Data Editor Mgt."; SelectFields: Page "DET Select Fields"; RecRefDuplicate: RecordRef; + xRecRef: RecordRef; NewFieldRef: FieldRef; FieldRefVar: FieldRef; + xFieldRefVar: FieldRef; begin if RecRef.Number() = 0 then exit; @@ -6579,11 +6630,16 @@ page 81000 "DET Data Editor Buffer" if Rec.FindSet() then repeat RecRef.Get(Rec."Source Record ID"); + xRecRef := RecRef.Duplicate(); FieldRefVar := RecRef.Field(TempDETField."Field Id"); + xFieldRefVar := xRecRef.Field(TempDETField."Field Id"); FieldRefVar.Value(NewFieldRef.Value()); if not WithoutValidate then FieldRefVar.Validate(); RecRef.Modify(not WithoutValidate); + if IsLogEnabled then + DataEditorMgt.LogModify(RecRef.Number(), FieldRefVar.Number(), RecRef.RecordId(), xFieldRefVar, + FieldRefVar, not WithoutValidate); until Rec.Next() = 0; LoadData(); end; @@ -6591,10 +6647,13 @@ page 81000 "DET Data Editor Buffer" local procedure CopyColumnToColumn() var TempDETField: Record "DET Field" temporary; + DataEditorMgt: Codeunit "DET Data Editor Mgt."; SelectFields: Page "DET Select Fields"; RecRefDuplicate: RecordRef; + xRecRef: RecordRef; CopyFromFieldRef: FieldRef; CopyToFieldRef: FieldRef; + xCopyToFieldRef: FieldRef; CopyToFieldNo, CopyFromFieldNo : Integer; begin if RecRef.Number() = 0 then @@ -6636,14 +6695,19 @@ page 81000 "DET Data Editor Buffer" if Rec.FindSet() then repeat RecRef.Get(Rec."Source Record ID"); + xRecRef := RecRef.Duplicate(); CopyFromFieldRef := RecRef.Field(CopyFromFieldNo); if CopyFromFieldRef.Class() = FieldClass::FlowField then CopyFromFieldRef.CalcField(); CopyToFieldRef := RecRef.Field(CopyToFieldNo); + xCopyToFieldRef := xRecRef.Field(CopyToFieldNo); CopyToFieldRef.Value(CopyFromFieldRef.Value()); if not WithoutValidate then CopyToFieldRef.Validate(); RecRef.Modify(not WithoutValidate); + if IsLogEnabled then + DataEditorMgt.LogModify(RecRef.Number(), CopyToFieldRef.Number(), RecRef.RecordId(), xCopyToFieldRef, + CopyToFieldRef, not WithoutValidate); until Rec.Next() = 0; LoadData(); end; @@ -6667,6 +6731,7 @@ page 81000 "DET Data Editor Buffer" local procedure InsertNewRecord() var + DataEditorMgt: Codeunit "DET Data Editor Mgt."; InsertNewRecordPage: Page "DET Insert New Record"; NewRecordId: RecordId; begin @@ -6679,18 +6744,28 @@ page 81000 "DET Data Editor Buffer" Rec.FindFirst(); Rec.SetPosition(Rec.GetPosition()); Rec.SetRange("Source Record ID"); + + if IsLogEnabled then + DataEditorMgt.LogInsert(RecRef.Number(), NewRecordId, not WithoutValidate); + Message(RecordIsInsertedLbl, NewRecordId); end; local procedure DeleteSourceRecord(SourceRecordID: RecordId) var + DataEditorMgt: Codeunit "DET Data Editor Mgt."; SourceRecRef: RecordRef; begin if SourceRecRef.Get(SourceRecordID) then SourceRecRef.Delete(not WithoutValidate); + + if IsLogEnabled then + DataEditorMgt.LogDelete(RecRef.Number(), SourceRecordID, not WithoutValidate); end; procedure LoadRecords(TableNo: Integer; inCustomTableView: Text; inFieldFilter: Text; inWithoutValidate: Boolean; inExcludeFlowFields: Boolean) + var + DataEditorSetup: Record "DET Data Editor Setup"; begin WithoutValidate := inWithoutValidate; ExcludeFlowFields := inExcludeFlowFields; @@ -6700,6 +6775,8 @@ page 81000 "DET Data Editor Buffer" InitVisibility(); InitEditable(); LoadData(); + if DataEditorSetup.Get() then + IsLogEnabled := DataEditorSetup."Enable Data Editor Log"; end; local procedure OpenRecord(TableNo: Integer) @@ -6790,41 +6867,53 @@ page 81000 "DET Data Editor Buffer" local procedure OnValidateField(FieldCounter: Integer; NewValue: Text[2048]) var DataEditorMgt: Codeunit "DET Data Editor Mgt."; + xRecRef: RecordRef; FieldRefVar: FieldRef; + xFieldRefVar: FieldRef; FieldInfo: Dictionary of [Integer, Text]; OriginalFieldNo: Integer; begin if not RecRef.Get(Rec."Source Record ID") then exit; + xRecRef := RecRef.Duplicate(); GenFieldInfoDict.Get(FieldCounter, FieldInfo); foreach OriginalFieldNo in FieldInfo.Keys() do FieldRefVar := RecRef.Field(OriginalFieldNo); + xFieldRefVar := xRecRef.Field(OriginalFieldNo); if DataEditorMgt.IsFieldIsPartOfPK(RecRef, FieldRefVar) then begin DataEditorMgt.RenamePKField(RecRef, FieldRefVar, Rec."Source Record ID", NewValue); + if IsLogEnabled then + DataEditorMgt.LogRename(RecRef.Number(), FieldRefVar.Number(), RecRef.RecordId(), xFieldRefVar, FieldRefVar, true); exit; end; - FieldRefVar.Value(TextValueAsVariant(FieldRefVar.Type(), NewValue)); + FieldRefVar.Value(DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue)); if not WithoutValidate then FieldRefVar.Validate(); RecRef.Modify(not WithoutValidate); + if IsLogEnabled then + DataEditorMgt.LogModify(RecRef.Number(), FieldRefVar.Number(), Rec."Source Record ID", xFieldRefVar, FieldRefVar, not WithoutValidate); end; local procedure OnDrillDownField(FieldCounter: Integer; var NewValue: Text[2048]) var TempNameValueBuffer: Record "Name/Value Buffer" temporary; DataEditorMgt: Codeunit "DET Data Editor Mgt."; + xRecRef: RecordRef; FieldRefVar: FieldRef; + xFieldRefVar: FieldRef; FieldInfo: Dictionary of [Integer, Text]; OriginalFieldNo: Integer; begin if not RecRef.Get(Rec."Source Record ID") then exit; + xRecRef := RecRef.Duplicate(); GenFieldInfoDict.Get(FieldCounter, FieldInfo); OriginalFieldNo := FieldInfo.Keys.Get(FieldInfo.Count()); FieldRefVar := RecRef.Field(OriginalFieldNo); + xFieldRefVar := xRecRef.Field(OriginalFieldNo); if not DataEditorMgt.GetNewColumnValue(RecRef, FieldRefVar, Rec."Source Record ID", TempNameValueBuffer) then exit; @@ -6837,76 +6926,9 @@ page 81000 "DET Data Editor Buffer" NewValue := TempNameValueBuffer.Value else NewValue := format(FieldRefVar.Value()); - end; - procedure TextValueAsVariant(FieldTypeVar: FieldType; ValueAsText: Text[2048]): Variant - var - DateFormulaValue: DateFormula; - IntegerValue: Integer; - DecimalValue: Decimal; - BooleanValue: Boolean; - DateValue: Date; - DateTimeValue: DateTime; - TimeValue: Time; - GuidValue: Guid; - BigIntegerValue: BigInteger; - begin - case FieldTypeVar of - FieldTypeVar::Code, FieldTypeVar::Text: - exit(ValueAsText); - FieldTypeVar::Integer: - begin - Evaluate(IntegerValue, ValueAsText); - exit(IntegerValue); - end; - FieldTypeVar::Decimal: - begin - Evaluate(DecimalValue, ValueAsText); - exit(DecimalValue); - end; - FieldTypeVar::Boolean: - begin - Evaluate(BooleanValue, ValueAsText); - exit(BooleanValue); - end; - FieldTypeVar::Date: - begin - Evaluate(DateValue, ValueAsText); - exit(DateValue); - end; - FieldTypeVar::DateFormula: - begin - Evaluate(DateFormulaValue, ValueAsText); - exit(DateFormulaValue); - end; - FieldTypeVar::DateTime: - begin - Evaluate(DateTimeValue, ValueAsText); - exit(DateTimeValue); - end; - FieldTypeVar::Time: - begin - Evaluate(TimeValue, ValueAsText); - exit(TimeValue); - end; - FieldTypeVar::Guid: - begin - Evaluate(GuidValue, ValueAsText); - exit(GuidValue); - end; - FieldTypeVar::BigInteger: - begin - Evaluate(BigIntegerValue, ValueAsText); - exit(BigIntegerValue); - end; - FieldTypeVar::Option: - begin - Evaluate(IntegerValue, ValueAsText); - exit(IntegerValue); - end; - else - exit(ValueAsText); - end; + if IsLogEnabled then + DataEditorMgt.LogModify(RecRef.Number(), FieldRefVar.Number(), Rec."Source Record ID", xFieldRefVar, FieldRefVar, not WithoutValidate); end; local procedure InitLoadFields(var inRecRef: RecordRef) @@ -7813,6 +7835,7 @@ page 81000 "DET Data Editor Buffer" RecRef: RecordRef; WithoutValidate: Boolean; ExcludeFlowFields: Boolean; + IsLogEnabled: Boolean; CustomTableView: text; FieldFilter: text; GenFieldInfoDict: Dictionary of [Integer, Dictionary of [Integer, Text]]; diff --git a/Pages/Pag81004.DETInsertNewRecord.al b/Pages/Pag81004.DETInsertNewRecord.al index 4ae138c..9453076 100644 --- a/Pages/Pag81004.DETInsertNewRecord.al +++ b/Pages/Pag81004.DETInsertNewRecord.al @@ -558,7 +558,7 @@ page 81004 "DET Insert New Record" local procedure OnValidateField(FieldCounter: Integer; NewValue: Text[2048]) var - DataEditorBufferPage: Page "DET Data Editor Buffer"; + DataEditorMgt: Codeunit "DET Data Editor Mgt."; FieldRefVar: FieldRef; FieldInfoDictionaty: Dictionary of [Integer, Text]; OriginalFieldNo: Integer; @@ -571,35 +571,35 @@ page 81004 "DET Insert New Record" case FieldCounter of 1: - VariantValue1 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue1 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 2: - VariantValue2 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue2 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 3: - VariantValue3 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue3 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 4: - VariantValue4 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue4 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 5: - VariantValue5 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue5 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 6: - VariantValue6 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue6 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 7: - VariantValue7 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue7 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 8: - VariantValue8 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue8 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 9: - VariantValue9 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue9 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 10: - VariantValue10 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue10 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 11: - VariantValue11 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue11 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 12: - VariantValue12 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue12 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 13: - VariantValue13 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue13 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 14: - VariantValue14 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue14 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); 15: - VariantValue15 := DataEditorBufferPage.TextValueAsVariant(FieldRefVar.Type(), NewValue); + VariantValue15 := DataEditorMgt.TextValueAsVariant(FieldRefVar.Type(), NewValue); end; end; diff --git a/Pages/Pag81007.DETFindandReplace.al b/Pages/Pag81007.DETFindandReplace.al index 9772ee6..f4bdd27 100644 --- a/Pages/Pag81007.DETFindandReplace.al +++ b/Pages/Pag81007.DETFindandReplace.al @@ -120,10 +120,14 @@ page 81007 "DET Find and Replace" local procedure FindAndReplaceAll(Replace: Boolean) var + DataEditorSetup: Record "DET Data Editor Setup"; + DataEditorMgt: Codeunit "DET Data Editor Mgt."; ResultNotification: Notification; RecRef: RecordRef; + xRecRef: RecordRef; RecRefToFilter: RecordRef; FieldRefToModify: FieldRef; + xFieldRefToModify: FieldRef; FieldRefVar: FieldRef; EntryNo: Integer; FieldCounter: Integer; @@ -132,9 +136,14 @@ page 81007 "DET Find and Replace" ReplacedCounter: Integer; ReplacedTotal: Integer; FieldNo: Integer; + IsLogEnabled: Boolean; begin Rec.Reset(); Rec.DeleteAll(); + + if DataEditorSetup.Get() then + IsLogEnabled := DataEditorSetup."Enable Data Editor Log"; + case true of MatchCase and MatchEntireFieldValue: FindWhatFilter := FindWhat; @@ -173,6 +182,7 @@ page 81007 "DET Find and Replace" Clear(FieldRefVar); Clear(RecRefToFilter); RecRefToFilter := RecRef.Duplicate(); + xRecRef := RecRef.Duplicate(); RecRefToFilter.FilterGroup(20); RecRefToFilter.SetRecFilter(); FieldRefVar := RecRefToFilter.Field(FieldNo); @@ -189,11 +199,15 @@ page 81007 "DET Find and Replace" Rec."Is Editable" := (FieldRefVar.Class = FieldRefVar.Class::Normal); if Replace and Rec."Is Editable" then begin FieldRefToModify := RecRef.Field(Rec."Field Number"); + xFieldRefToModify := xRecRef.Field(Rec."Field Number"); FieldRefToModify.Value(ReplaceWith); Rec."Field Value" := CopyStr(ReplaceWith, 1, MaxStrLen(Rec."Field Value")); if not GlobalWithoutValidate then FieldRefToModify.Validate(); ReplacedCounter += 1; + if IsLogEnabled then + DataEditorMgt.LogModify(RecRef.Number(), FieldRefToModify.Number(), RecRef.RecordId(), xFieldRefToModify, + FieldRefToModify, not GlobalWithoutValidate); end; Rec.Insert(); end; @@ -228,14 +242,19 @@ page 81007 "DET Find and Replace" local procedure OnFieldEdit(IsDrillDown: Boolean; FieldNo: Integer; var NewValue: Text[2048]) var + DataEditorSetup: Record "DET Data Editor Setup"; TempNameValueBuffer: Record "Name/Value Buffer" temporary; DataEditorMgt: Codeunit "DET Data Editor Mgt."; RecRef: RecordRef; + xRecRef: RecordRef; FieldRefVar: FieldRef; + xFieldRefVar: FieldRef; begin if not RecRef.Get(Rec."Record Id") then exit; + xRecRef := RecRef.Duplicate(); FieldRefVar := RecRef.Field(FieldNo); + xFieldRefVar := xRecRef.Field(FieldNo); if not IsDrillDown then FieldRefVar.Value(NewValue) @@ -251,6 +270,13 @@ page 81007 "DET Find and Replace" NewValue := TempNameValueBuffer.Value else NewValue := format(FieldRefVar.Value()); + + if not DataEditorSetup.Get() then + exit; + + if DataEditorSetup."Enable Data Editor Log" then + DataEditorMgt.LogModify(RecRef.Number(), FieldRefVar.Number(), RecRef.RecordId(), xFieldRefVar, + FieldRefVar, not GlobalWithoutValidate); end; procedure SetRecordInfo(TableNo: Integer; TableName: Text; WithoutValidate: Boolean; TableView: Text) diff --git a/Pages/Pag81009.DETDataEditorSetup.al b/Pages/Pag81009.DETDataEditorSetup.al new file mode 100644 index 0000000..d8cb000 --- /dev/null +++ b/Pages/Pag81009.DETDataEditorSetup.al @@ -0,0 +1,53 @@ +page 81009 "DET Data Editor Setup" +{ + ApplicationArea = All; + Caption = 'Data Editor Setup'; + PageType = Card; + SourceTable = "DET Data Editor Setup"; + UsageCategory = Administration; + + layout + { + area(Content) + { + group(General) + { + Caption = 'General'; + + field("Enable Data Editor Log"; Rec."Enable Data Editor Log") + { + ToolTip = 'May adversely affect performance.', Comment = '%'; + } + } + } + } + actions + { + area(Promoted) + { + actionref(DataEditorLog_promoted; DataEditorLog) + { + + } + } + area(Processing) + { + action(DataEditorLog) + { + ApplicationArea = All; + Caption = 'Data Editor Log'; + ToolTip = 'Data Editor Log'; + Image = ShowList; + RunObject = page "DET Data Editor Log"; + } + } + } + trigger OnOpenPage() + begin + Rec.Reset(); + if not Rec.Get() then begin + Rec.Init(); + Rec.Insert(true); + end; + end; +} diff --git a/Pages/Pag81010.DETDataEditorLog.al b/Pages/Pag81010.DETDataEditorLog.al new file mode 100644 index 0000000..ad9673f --- /dev/null +++ b/Pages/Pag81010.DETDataEditorLog.al @@ -0,0 +1,116 @@ +page 81010 "DET Data Editor Log" +{ + ApplicationArea = All; + Caption = 'Data Editor Log'; + PageType = List; + SourceTable = "DET Data Editor Log"; + UsageCategory = Lists; + ModifyAllowed = false; + InsertAllowed = false; + DeleteAllowed = false; + SourceTableView = sorting("Entry No.") order(descending); + + layout + { + area(Content) + { + repeater(General) + { + field("Entry No."; Rec."Entry No.") + { + ToolTip = 'Specifies the value of the Entry No. field.', Comment = '%'; + } + field("Record Id"; Format(Rec."Record Id")) + { + Caption = 'Record Id'; + ToolTip = 'Specifies the value of the Record Id field.', Comment = '%'; + } + field("Table No."; Rec."Table No.") + { + ToolTip = 'Specifies the value of the Table No. field.', Comment = '%'; + } + field("Table Name"; Rec."Table Name") + { + ToolTip = 'Specifies the value of the Table Name field.', Comment = '%'; + } + field("Field No."; Rec."Field No.") + { + ToolTip = 'Specifies the value of the Field No. field.', Comment = '%'; + } + field("Field Name"; Rec."Field Name") + { + ToolTip = 'Specifies the value of the Field Name field.', Comment = '%'; + } + field("Action Type"; Rec."Action Type") + { + ToolTip = 'Specifies the value of the Action Type field.', Comment = '%'; + } + field("Old Value"; Rec."Old Value") + { + ToolTip = 'Specifies the value of the Old Value field.', Comment = '%'; + } + field("New Value"; Rec."New Value") + { + ToolTip = 'Specifies the value of the New Value field.', Comment = '%'; + } + field("With Validation"; Rec."With Validation") + { + ToolTip = 'Specifies the value of the With Validation field.', Comment = '%'; + } + field(SystemCreatedAt; Rec.SystemCreatedAt) + { + Caption = 'Created At'; + ToolTip = 'Specifies the value of the SystemCreatedAt field.', Comment = '%'; + } + field(SystemCreatedBy; Rec.GetUserName()) + { + Caption = 'Created By'; + ToolTip = 'Specifies the value of the SystemCreatedBy field.', Comment = '%'; + } + } + } + } + actions + { + area(Promoted) + { + actionref(ShowOldValue_promoted; ShowOldValue) + { + + } + actionref(ShowNewValue_promoted; ShowNewValue) + { + + } + } + area(Processing) + { + action(ShowOldValue) + { + ApplicationArea = All; + Caption = 'Show Old Value'; + ToolTip = 'Show Old Value'; + Image = ShowList; + trigger OnAction() + begin + Message(Rec.GetBLOBDataAsTxt(Rec.FieldNo("Old Value BLOB"), TextEncoding::UTF8)); + end; + } + action(ShowNewValue) + { + ApplicationArea = All; + Caption = 'Show New Value'; + ToolTip = 'Show New Value'; + Image = ShowList; + trigger OnAction() + begin + Message(Rec.GetBLOBDataAsTxt(Rec.FieldNo("New Value BLOB"), TextEncoding::UTF8)); + end; + } + } + } + trigger OnOpenPage() + begin + if Rec.FindFirst() then; // For some reason, the page shows the last record when we use descending sorting. This is a hotfix. + end; +} diff --git a/Pages/Pag81011.DETImportExportDialog.al b/Pages/Pag81011.DETImportExportDialog.al new file mode 100644 index 0000000..8a986be --- /dev/null +++ b/Pages/Pag81011.DETImportExportDialog.al @@ -0,0 +1,30 @@ +page 81011 "DET Import/Export Dialog" +{ + ApplicationArea = All; + Caption = 'Import/Export Dialog'; + PageType = StandardDialog; + + layout + { + area(Content) + { + group(General) + { + field(ImportOnFind; ImportOnFind) + { + ApplicationArea = All; + Caption = 'Import On Find'; + ToolTip = 'Action to do when imported record is already exist in database'; + } + } + } + } + + procedure GetImportOnFind(): Enum "DET Import On Find" + begin + exit(ImportOnFind); + end; + + var + ImportOnFind: Enum "DET Import On Find"; +} diff --git a/Permissions/PermissionSet81000.DETDataEditorTool.al b/Permissions/PermissionSet81000.DETDataEditorTool.al index 7fe7e7b..31de377 100644 --- a/Permissions/PermissionSet81000.DETDataEditorTool.al +++ b/Permissions/PermissionSet81000.DETDataEditorTool.al @@ -20,5 +20,10 @@ permissionset 81000 "DET Data Editor Tool" page "DET Key" = X, table "DET Query Preset" = X, tabledata "DET Query Preset" = RMID, - page "DET Query Preset" = X; + page "DET Query Preset" = X, + tabledata "DET Data Editor Setup" = RIMD, + table "DET Data Editor Setup" = X, + tabledata "DET Data Editor Log" = RIMD, + table "DET Data Editor Log" = X, + page "DET Data Editor Setup" = X; } \ No newline at end of file diff --git a/Tables/Tab81004.DETDataEditorSetup.al b/Tables/Tab81004.DETDataEditorSetup.al new file mode 100644 index 0000000..90147b6 --- /dev/null +++ b/Tables/Tab81004.DETDataEditorSetup.al @@ -0,0 +1,24 @@ +table 81004 "DET Data Editor Setup" +{ + Caption = 'Data Editor Setup'; + DataClassification = CustomerContent; + + fields + { + field(1; "Primary Key"; Code[10]) + { + Caption = 'Primary Key'; + } + field(2; "Enable Data Editor Log"; Boolean) + { + Caption = 'Enable Data Editor Log'; + } + } + keys + { + key(PK; "Primary Key") + { + Clustered = true; + } + } +} diff --git a/Tables/Tab81005.DETDataEditorLog.al b/Tables/Tab81005.DETDataEditorLog.al new file mode 100644 index 0000000..19d6f2f --- /dev/null +++ b/Tables/Tab81005.DETDataEditorLog.al @@ -0,0 +1,128 @@ +table 81005 "DET Data Editor Log" +{ + Caption = 'Data Editor Log'; + DataClassification = CustomerContent; + + fields + { + field(1; "Entry No."; BigInteger) + { + Caption = 'Entry No.'; + } + field(2; "Table No."; Integer) + { + Caption = 'Table No.'; + TableRelation = AllObjWithCaption."Object ID" where("Object Type" = const(Table)); + } + field(3; "Table Name"; Text[300]) + { + Caption = 'Table Name'; + CalcFormula = lookup(AllObjWithCaption."Object Name" where("Object Type" = const(Table), "Object ID" = field("Table No."))); + FieldClass = FlowField; + Editable = false; + } + field(4; "Field No."; Integer) + { + Caption = 'Field No.'; + TableRelation = Field."No." where(TableNo = field("Table No.")); + } + field(5; "Field Name"; Text[300]) + { + Caption = 'Field Name'; + CalcFormula = lookup(Field.FieldName where(TableNo = field("Table No."), "No." = field("Field No."))); + FieldClass = FlowField; + Editable = false; + } + field(6; "Action Type"; Enum "DET Log Action Type") + { + Caption = 'Action Type'; + } + field(7; "Old Value"; Text[2048]) + { + Caption = 'Old Value'; + } + field(8; "New Value"; Text[2048]) + { + Caption = 'New Value'; + } + field(9; "Old Value BLOB"; Blob) + { + Caption = 'Old Value BLOB'; + } + field(10; "New Value BLOB"; Blob) + { + Caption = 'New Value BLOB'; + } + field(11; "With Validation"; Boolean) + { + Caption = 'With Validation'; + } + field(12; "Record Id"; RecordId) + { + Caption = 'Record Id'; + } + } + keys + { + key(PK; "Entry No.") + { + Clustered = true; + } + key(ModifiedKey; SystemModifiedAt) + { + + } + } + + procedure GetBLOBDataAsTxt(FieldNo: Integer; Encoding: TextEncoding) Result: Text + var + TempBlob: Codeunit "Temp Blob"; + TypeHelper: Codeunit "Type Helper"; + RecRef: RecordRef; + DataFieldRef: FieldRef; + ResponseInStream: InStream; + TextBuffer: Text; + begin + RecRef.GetTable(Rec); + DataFieldRef := RecRef.Field(FieldNo); + if DataFieldRef.Type <> DataFieldRef.Type::Blob then + exit; + DataFieldRef.CalcField(); + + TempBlob.FromFieldRef(DataFieldRef); + + if not TempBlob.HasValue() then + exit; + + TempBlob.CreateInStream(ResponseInStream, Encoding); + while not ResponseInStream.EOS() do begin + ResponseInStream.ReadText(TextBuffer); + Result += TextBuffer + TypeHelper.CRLFSeparator(); + end; + end; + + + procedure SetBLOBTextData(FieldNo: Integer; TextData: Text; Encoding: TextEncoding) + var + ResponseOutStream: OutStream; + begin + case FieldNo of + Rec.FieldNo("Old Value BLOB"): + Rec."Old Value BLOB".CreateOutStream(ResponseOutStream, Encoding); + Rec.FieldNo("New Value BLOB"): + Rec."New Value BLOB".CreateOutStream(ResponseOutStream, Encoding); + end; + + ResponseOutStream.WriteText(TextData); + + Rec.Modify(true); + end; + + procedure GetUserName(): Text + var + User: Record User; + begin + if User.Get(Rec.SystemCreatedBy) then + exit(User."User Name"); + end; +} diff --git a/Translations/Data Editor Tool.g.xlf b/Translations/Data Editor Tool.g.xlf index 339bd59..a4725cb 100644 --- a/Translations/Data Editor Tool.g.xlf +++ b/Translations/Data Editor Tool.g.xlf @@ -2023,6 +2023,86 @@ Table DET Data Editor Buffer - Field Without Validate - Property Caption + + Data Editor Log + + Table DET Data Editor Log - Property Caption + + + Action Type + + Table DET Data Editor Log - Field Action Type - Property Caption + + + Entry No. + + Table DET Data Editor Log - Field Entry No. - Property Caption + + + Field Name + + Table DET Data Editor Log - Field Field Name - Property Caption + + + Field No. + + Table DET Data Editor Log - Field Field No. - Property Caption + + + New Value + + Table DET Data Editor Log - Field New Value - Property Caption + + + New Value BLOB + + Table DET Data Editor Log - Field New Value BLOB - Property Caption + + + Old Value + + Table DET Data Editor Log - Field Old Value - Property Caption + + + Old Value BLOB + + Table DET Data Editor Log - Field Old Value BLOB - Property Caption + + + Record Id + + Table DET Data Editor Log - Field Record Id - Property Caption + + + Table Name + + Table DET Data Editor Log - Field Table Name - Property Caption + + + Table No. + + Table DET Data Editor Log - Field Table No. - Property Caption + + + With Validation + + Table DET Data Editor Log - Field With Validation - Property Caption + + + Data Editor Setup + + Table DET Data Editor Setup - Property Caption + + + Enable Data Editor Log + + Table DET Data Editor Setup - Field Enable Data Editor Log - Property Caption + + + Primary Key + + Table DET Data Editor Setup - Field Primary Key - Property Caption + Field @@ -2113,11 +2193,31 @@ Table DET Query Preset - Field Preset Json - Property Caption + + Import is finished. + + Codeunit DET Data Editor Mgt. - NamedType ImportFinishedLbl + + + Inserted: %1 + %1 = Inserted record count + Codeunit DET Data Editor Mgt. - NamedType InsertedLbl + + + Modified: %1 + %1 = Modified record count + Codeunit DET Data Editor Mgt. - NamedType ModifiedLbl + Changing the primary key for >15 values is not supported. Codeunit DET Data Editor Mgt. - NamedType RenamePKNotSuppErr + + Skipped: %1 + %1 = Skipped record count + Codeunit DET Data Editor Mgt. - NamedType SkippedLbl + Data Editor @@ -4308,6 +4408,26 @@ Page DET Data Editor Buffer - Action DET Update Column - Property Caption + + Export Table Data, only loaded fields will be exported. + + Page DET Data Editor Buffer - Action ExportTableData - Property ToolTip + + + Export Table Data + + Page DET Data Editor Buffer - Action ExportTableData - Property Caption + + + Import Table Data, depends on previously selected validation. + + Page DET Data Editor Buffer - Action ImportTableData - Property ToolTip + + + Import Table Data + + Page DET Data Editor Buffer - Action ImportTableData - Property Caption + Insert new record @@ -4328,6 +4448,131 @@ Page DET Data Editor Buffer - Action Refresh - Property Caption + + Data Editor Log + + Page DET Data Editor Log - Property Caption + + + Specifies the value of the Action Type field. + % + Page DET Data Editor Log - Control Action Type - Property ToolTip + + + Specifies the value of the Entry No. field. + % + Page DET Data Editor Log - Control Entry No. - Property ToolTip + + + Specifies the value of the Field Name field. + % + Page DET Data Editor Log - Control Field Name - Property ToolTip + + + Specifies the value of the Field No. field. + % + Page DET Data Editor Log - Control Field No. - Property ToolTip + + + Specifies the value of the New Value field. + % + Page DET Data Editor Log - Control New Value - Property ToolTip + + + Specifies the value of the Old Value field. + % + Page DET Data Editor Log - Control Old Value - Property ToolTip + + + Specifies the value of the Record Id field. + % + Page DET Data Editor Log - Control Record Id - Property ToolTip + + + Record Id + + Page DET Data Editor Log - Control Record Id - Property Caption + + + Specifies the value of the SystemCreatedAt field. + % + Page DET Data Editor Log - Control SystemCreatedAt - Property ToolTip + + + Created At + + Page DET Data Editor Log - Control SystemCreatedAt - Property Caption + + + Specifies the value of the SystemCreatedBy field. + % + Page DET Data Editor Log - Control SystemCreatedBy - Property ToolTip + + + Created By + + Page DET Data Editor Log - Control SystemCreatedBy - Property Caption + + + Specifies the value of the Table Name field. + % + Page DET Data Editor Log - Control Table Name - Property ToolTip + + + Specifies the value of the Table No. field. + % + Page DET Data Editor Log - Control Table No. - Property ToolTip + + + Specifies the value of the With Validation field. + % + Page DET Data Editor Log - Control With Validation - Property ToolTip + + + Show New Value + + Page DET Data Editor Log - Action ShowNewValue - Property ToolTip + + + Show New Value + + Page DET Data Editor Log - Action ShowNewValue - Property Caption + + + Show Old Value + + Page DET Data Editor Log - Action ShowOldValue - Property ToolTip + + + Show Old Value + + Page DET Data Editor Log - Action ShowOldValue - Property Caption + + + Data Editor Setup + + Page DET Data Editor Setup - Property Caption + + + General + + Page DET Data Editor Setup - Control General - Property Caption + + + May adversely affect performance. + % + Page DET Data Editor Setup - Control Enable Data Editor Log - Property ToolTip + + + Data Editor Log + + Page DET Data Editor Setup - Action DataEditorLog - Property ToolTip + + + Data Editor Log + + Page DET Data Editor Setup - Action DataEditorLog - Property Caption + Edit Value @@ -4433,6 +4678,21 @@ Page DET Find and Replace - Action FindReplaceAll - Property Caption + + Import/Export Dialog + + Page DET Import/Export Dialog - Property Caption + + + Action to do when imported record is already exist in database + + Page DET Import/Export Dialog - Control ImportOnFind - Property ToolTip + + + Import On Find + + Page DET Import/Export Dialog - Control ImportOnFind - Property Caption + Insert New Record @@ -4693,6 +4953,46 @@ Page DET Select Fields - Action Set Included - Property Caption + + Error + + Enum DET Import On Find - EnumValue Error - Property Caption + + + Modify + + Enum DET Import On Find - EnumValue Modify - Property Caption + + + Skip + + Enum DET Import On Find - EnumValue Skip - Property Caption + + + + + Enum DET Log Action Type - EnumValue - Property Caption + + + Delete + + Enum DET Log Action Type - EnumValue Delete - Property Caption + + + Insert + + Enum DET Log Action Type - EnumValue Insert - Property Caption + + + Modify + + Enum DET Log Action Type - EnumValue Modify - Property Caption + + + Rename + + Enum DET Log Action Type - EnumValue Rename - Property Caption + Data Editor Tool diff --git a/Volodymyr Dvernytskyi_Data Editor Tool_2.0.1.6.app b/Volodymyr Dvernytskyi_Data Editor Tool_2.0.1.6.app deleted file mode 100644 index 2c00c3e..0000000 Binary files a/Volodymyr Dvernytskyi_Data Editor Tool_2.0.1.6.app and /dev/null differ diff --git a/Volodymyr Dvernytskyi_Data Editor Tool_3.0.0.0.app b/Volodymyr Dvernytskyi_Data Editor Tool_3.0.0.0.app new file mode 100644 index 0000000..02919b6 Binary files /dev/null and b/Volodymyr Dvernytskyi_Data Editor Tool_3.0.0.0.app differ diff --git a/Volodymyr Dvernytskyi_Data Editor Tool_Latest.app b/Volodymyr Dvernytskyi_Data Editor Tool_Latest.app new file mode 100644 index 0000000..02919b6 Binary files /dev/null and b/Volodymyr Dvernytskyi_Data Editor Tool_Latest.app differ diff --git a/app.json b/app.json index 6f04ef3..ec06ad2 100644 --- a/app.json +++ b/app.json @@ -2,7 +2,7 @@ "id": "e28d62da-ceb0-46e7-9e06-774bc46f4bac", "name": "Data Editor Tool", "publisher": "Volodymyr Dvernytskyi", - "version": "2.0.1.6", + "version": "3.0.0.0", "brief": "https://vld-nav.com/", "description": "https://vld-nav.com/", "privacyStatement": "https://vld-nav.com/",