Eine weitere immer wieder auftauchende Anforderung ist das automatische Splitten von Kommentaren.

Hier allerdings doch bitte nicht alle X Zeichen, sondern zwischen den Wörtern.

Eine Funktion hierfür kann z.B. so aussehen (Beispiel mit Sales Comment Line).

AddHeaderText(SalesHeader : Record "Sales Header";CommentCode : Code[10];NewText : Text;OrderLineNo : Integer)

Local Variables
Name			DataType	Subtype			Length
SalesCommentLine	Record		Sales Comment Line	
RemainingText		Text		
LastSpacePos		Integer		
SpacePos		Integer		
LineNo			Integer		

IF NewHeaderText = '' THEN
  EXIT; // NO TEXT -> NO COMMENT -> NO EMPTY LINES
// INSERT EMPTY COMMENT LINE BEFORE EXIT, IF YOU WANT TO ALLOW EMPTY LINES  
SalesCommentLine.SETRANGE("Document Type",SalesHeader."Document Type");
SalesCommentLine.SETRANGE("Document No.",SalesHeader."No.");
SalesCommentLine.SETRANGE("Document Line No.",OrderLineNo);
IF SalesCommentLine.FINDLAST THEN
  LineNo := SalesCommentLine."Line No."
ELSE
  LineNo := 0;
SalesCommentLine.RESET;
SalesCommentLine."Document Type" := SalesHeader."Document Type";
SalesCommentLine."Document No." := SalesHeader."No.";
SalesCommentLine."Document Line No." := OrderLineNo;
SalesCommentLine.Date := WORKDATE;
SalesCommentLine.Code := CommentCode;
RemainingText := NewText;
REPEAT
  IF STRLEN(RemainingText) > 80 THEN BEGIN // COMMENT HAS MORE THEN 80  CHARACTERS
    LastSpacePos := 0;
    REPEAT
      SpacePos := STRPOS(COPYSTR(RemainingText,LastSpacePos + 1),' '); // FIND NEXT SPACE
      IF LastSpacePos + SpacePos < 80 THEN
        LastSpacePos := LastSpacePos + SpacePos + 1;
    UNTIL (SpacePos = 0) OR (LastSpacePos + SpacePos >= 80);
	IF LastSpacePos = 0 THEN
		LastSpacePos = 80; // NO SPACE IN THE FIRST 80 CHARACTERS FOUND
    LineNo := LineNo + 10000;
    SalesCommentLine."Line No." := LineNo;
    SalesCommentLine.Comment := COPYSTR(RemainingText,1,LastSpacePos - 2);
    RemainingText := COPYSTR(RemainingText,LastSpacePos);
    SalesCommentLine.INSERT;
  END ELSE BEGIN // LESS THEN 80 CHARACTERS LEFT, NO MORE SPLITTING NEEDED
    LineNo := LineNo + 10000;
    SalesCommentLine."Line No." := LineNo;
    SalesCommentLine.Comment := RemainingText;
    SalesCommentLine.INSERT;
    RemainingText := '';
  END;
UNTIL RemainingText = '';

 

Diese Woche bin ich auf ein eher störendes Phänomen bei der Entwicklung in einer NAV 2013 R2 CU12 Datenbank gestosen. (Das verhalten konnte ich inzwischen auch in älteren Build-Versionen nachstellen)

Ich lege eine neue Tabelle an, erzeuge eine Page dazu und klicke auf RUN.

SQL-Fehler: Tabelle kann nicht gefunden werden.

Kurzer Blick auf dem Server, die Tabelle fehlt tatsächlich.

Export -> Lösche -> Import -> Tabelle fehlt

Sync-NAVTenant im Powershell aufrufen -> kein Fehler -> Tabelle fehlt

Neustart NST -> Tabelle fehlt -> Start RTC -> Tabelle wird angelegt

 

Diese Verhalten war Problemlos jederzeit reproduzierbar. Doch wo kam es her? An CU12 scheint es nicht zu liegen.

Fragen wir doch mal das Internet: Keine der üblichen Suchen bringt etwas das helfen könnte.

Dann hat es mir doch noch gedämmert: Es sieht so aus als ob der Trigger in der Object Metadata Tabelle fehlt.

Kurzer Blick: Stimmt, der ist nicht da.

 

Wie habe ich das den geschafft?

Mein Vorgehen war so:

– Neue Datenbank über SQL anlegen

– Import einer NAVDATA-Sicherung inkl. aller Objekte und Daten

 

In der Dev-Enviroment sieht alles gut aus. Der RTC läuft auch stabil.

 

Zum Schluß dann noch wie das ganze zu korrigieren ist:

Der Trigger lässt sich über SQL anlegen:

/****** Object: Trigger [dbo].[$ndo$objecttracking] Script Date: 23.10.2014 08:38:20 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER [dbo].[$ndo$objecttracking] ON [dbo].[Object Metadata] FOR DELETE, INSERT, UPDATE AS SET NOCOUNT ON DECLARE @delCount INTEGER, @insCount INTEGER, @updatedRows INTEGER, @currentDBTS BIGINT SELECT @delCount = COUNT(*) FROM DELETED SELECT @insCount = COUNT(*) FROM INSERTED SELECT @updatedRows = 0 SELECT @currentDBTS = CAST(@@DBTS AS BIGINT) IF (@insCount > 0) BEGIN UPDATE [dbo].[Object Tracking] SET [Object Timestamp] = @currentDBTS FROM INSERTED AS I JOIN [dbo].[Object Tracking] AS T ON (T.[Object Type] = I.[Object Type] AND T.[Object ID] = I.[Object ID] AND T.[Change Type] = 0) SELECT @updatedRows = @@ROWCOUNT IF (@updatedRows < @insCount) BEGIN INSERT INTO [dbo].[Object Tracking] ([Object Type], [Object ID], [Change Type], [Object Timestamp]) SELECT I.[Object Type], I.[Object ID], 0, @currentDBTS FROM INSERTED AS I LEFT OUTER JOIN [dbo].[Object Tracking] AS T ON (I.[Object Type] = T.[Object Type] AND I.[Object ID] = T.[Object ID] AND T.[Change Type] = 0) WHERE T.[Object Type] IS NULL AND T.[Object ID] IS NULL END END IF (@delCount > 0) BEGIN IF (@updatedRows = 0) BEGIN UPDATE [dbo].[Object Tracking] SET [Object Timestamp] = @currentDBTS FROM DELETED AS D JOIN [dbo].[Object Tracking] AS T ON (T.[Object Type] = D.[Object Type] AND T.[Object ID] = D.[Object ID] AND T.[Change Type] = 0) SELECT @updatedRows = @@ROWCOUNT END IF (@updatedRows < @delCount) BEGIN INSERT INTO [dbo].[Object Tracking] ([Object Type], [Object ID], [Change Type], [Object Timestamp]) SELECT D.[Object Type], D.[Object ID], 0, @currentDBTS FROM DELETED AS D LEFT OUTER JOIN [dbo].[Object Tracking] AS T ON (D.[Object Type] = T.[Object Type] AND D.[Object ID] = T.[Object ID] AND T.[Change Type] = 0) WHERE T.[Object Type] IS NULL AND T.[Object ID] IS NULL END END GO