navision- looping through line nos in sales line - loops

i am trying to retrieve the difference of qty and qts shipped for a sales order.
i am doing this through code.
setting range on sales line table fields and using findset does loop through all lines properly but while printing it gives the difference frm the last line.
clearing the variable is also not working.
i am new to NAV 2013 so not able to find out how to loop through all this lines so that it displays result properly.i tried using findfirst inside the if loop but no success.

You need to add to "Value", not overwrite it. (use +=, not :=)
CLEAR(Value);
SalesLine.RESET;
SalesLine.SETRANGE(SalesLine."Document No.","No.");
IF SalesLine.FINDSET THEN REPEAT
Value += SalesLine.Quantity - SalesLine."Quantity Shipped";
//MESSAGE('%1',Value);
UNTIL SalesLine.NEXT =0;

Try this code
local procedure DailyCalc(DailyLotNumber: Query DailyLotNumber): Decimal
var
SalesLine: Record "Sales Line";
NewRec: Decimal;
begin
SalesLine.SetRange("Document No.", DailyLotNumber.No_);
SalesLine.SetRange("Document Type", DailyLotNumber.Document_Type);
if SalesLine.FindSet() then begin
repeat
repeat
NewRec += (SalesLine.Quantity - SalesLine."Quantity Shipped") * SalesLine."Unit Price";
until SalesLine.Next() = 0;
exit(NewRec);
until SalesLine.Next() = 0;
end;
end;

Related

PHPSpreadsheet to update an existing file writes only the last record of the query

Hello i am trying to write an existing xlsx file using phpspreadsheet with setActiveSheetIndexByName(sheetname) and setcellvalue with reference and value, but it updates only the last record. spent more than 12 hours on this.
i tried foreach instead of while and used a counter to increment, but none worked.
<?php
include_once('db.php');
$prospect = $_REQUEST['prospect'];
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$sql1 = mysqli_query($db,"select filename,sheetname, row, responsecol,compliancecol,response, compliance from spreadsheet where `prospect`='$prospect' and response <>'' order by row");
//$row=1;
while($row1 = mysqli_fetch_assoc($sql1))
{
$filename= $row1['filename']; //test.xlsx
$sheetname= $row1['sheetname']; // mysheet
$responsecol= $row1['responsecol'].$row1['row']; //D1
$response= $row1['response']; //response
$compliancecol= $row1['compliancecol'].$row1['row']; //C1
$compliance= $row1['compliance']; //compliance
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($filename);
$spreadsheet->setActiveSheetIndexByName($sheetname)
->setCellValue($compliancecol,$compliance)
->setCellValue($responsecol,$response);
//$row++;
}
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save("newfile.xlsx");
exit;
?>
i wish each of the row from mysqli result updates each reference cell with value.
The easys way is to set a Limit of 1 to your MySQL query. That takes only one value from your data. If you will the last you should sort DESC.
$sql1 = mysqli_query($db,"select filename,sheetname, row, responsecol,compliancecol,response, compliance from spreadsheet where `prospect`='$prospect' and response <>'' order by row DESC LIMIT 1");

Output ZIP dataset

I am looking for some help with creating a macro utilizing an array as well as DO and IF statements for subsetting. Within my macro statement I am trying to look across columns for variables, and if the variable has a specific diagnosis code to then create a new variable and label as 1, and if not label all others as 0 to create one new data set based on that new variable, sort that data set, and append it to other data sets (because the input data sets are broken down quarterly), thus creating one final data set that I can then export (preferably as a newly created ZIP file to keep storage space down). I am using SAS 9.4/ Enterprise Guide 7.1.
Code:
OPTIONS MERROR SERROR SOURCE MLOGIC SYMBOLGEN MINOPERATOR OBS=MAX;
%MACRO DIAGXX(a,b);
DATA NEW;
SET x.&a(KEEP= PATID DIAG1-DIAG5);
ARRAY &b{5} $ DIAG1-DIAG5;
DO I = 1 TO 5;
IF &b{I} IN ("1630" "1631" "1638" "1639") THEN MESO = 1;
ELSE MESO = 0;
END;
DROP I;
RUN;
PROC SORT DATA=NEW NODUPKEY;
BY PATID;
WHERE MESO=1;
RUN;
PROC APPEND BASE=ALLDATA1 DATA=NEW FORCE;
RUN;
PROC EXPORT
DATA=ALLDATA1
OUTFILE= "C:\x\x\DIAGNOSIS EXPORT\MACRO DIAGXX MESO.CSV"
REPLACE
DBMS=CSV;
RUN;
%MEND DIAGXX;
%DIAGXX(Q1,MESTH);
%DIAGXX(Q2,MESTH);
You probably want to create your MESO flag this way so that the presence of any of the codes in any of the variables in the array will set MESO to true and it will be false when the codes never appear in any of the variables.
MESO = 0;
DO I = 1 TO 5;
IF &b{I} IN ("1630" "1631" "1638" "1639") THEN MESO = 1;
END;
If you want to get fancy you might save a little time by stopping the loop once the code is found.
DO I = 1 TO 5 WHILE (MESO=0);

How to index a table automatically and loop it in ipairs while keeping all data?

Table:
localization_strings = {
string_1 = "Text Here",
string_2 = "Some More Text Here",
string_3 = "More Text"
}
This is obviously not the whole table, but just a small sample. The real table is over 500+ lines. The reason I don't just redo the table is because other functions reference it and I don't have access to those files to fix them, so I have to find a work around. Also, because it would quite tedious work and can cause problems with other codes.
I have made 2 attempts at solving this problem, but I can only get one of the values I want (incorrect terminology, I think) and I need both as 1 is display text and 1 is data for a function call.
Attempts:
-- Attempt #1
-- Gives me the string_#'s but not the "Text"...which I need, as I want to display the text via another function
LocalizationUnorderedOpts = {}
LocalizationOpts = {}
for n,unordered_names in pairs(localization_strings) do
if (unordered_names) then
table.insert( LocalizationUnorderedOpts, n)
end
end
io.write(tostring(LocalizationUnorderedOpts) .. "\n")
table.sort(LocalizationUnorderedOpts)
for i,n in ipairs(LocalizationUnorderedOpts) do
if (n) then
io.write(tostring(i))
table.insert( LocalizationOpts, { text = tostring(LocalizationUnorderedOpts[i]), callback = function_pointer_does_not_matter, data = i } )
end
end
-- Attempt #2
-- Gives me the "Text" but not the string_#'s...which I need to as data to the callback to another function (via function pointer)
LocalizationUnorderedOpts = {}
LocalizationOpts = {}
for n,unordered_names in pairs(localization_strings) do
if (unordered_names) then
table.insert( LocalizationUnorderedOpts, localization_strings[n])
end
end
io.write(tostring(LocalizationUnorderedOpts) .. "\n")
table.sort(LocalizationUnorderedOpts)
for i,n in ipairs(LocalizationUnorderedOpts) do
if (n) then
io.write(tostring(i))
table.insert( LocalizationOpts, { text = tostring(LocalizationUnorderedOpts[i]), callback = function_pointer_does_not_matter, data = i } )
end
end
If I understand it correctly, you need to sort the non-array table. Your first attempt has done most of the work: build another table, which has the values the same as the keys in the original table.
What's left is how to get the original values like "Text Here", for that you need to index the original table:
for k, v in ipairs(LocalizationUnorderedOpts) do
print(v) --original key
print(localization_strings[v]) --original value
end

Nested loop conditional

Supposed I have this table:
TDID TDLINE
F04 04-AA
F04 04-BB <-- call a function
F05 05-AA
F05 05-BB <-- call a function
F06 06-AA <-- call a function
I would like to call a function while the TDID field is not the same as the previous one. I have the code below, it works but somehow it's not perfectly works (it missed the last row):
LOOP AT lines ASSIGNING <fs1>.
IF <fs2> IS INITIAL.
<fs2> = <fs1>.
ELSE.
li_line-tdline = <fs2>-tdline.
APPEND li_line.
IF <fs1>-tdid NE <fs2>-tdid.
li_thead-tdid = <fs2>-tdid.
CALL FUNCTION 'SAVE_TEXT'
EXPORTING
header = li_thead
savemode_direct = 'X'
TABLES
lines = li_line
CLEAR: li_thead,
li_line.
FREE: li_thead,
li_line.
ENDIF.
ENDIF.
ENDLOOP.
ANSWER
Thank you to vwegert for the answer:
LOOP AT lines ASSIGNING <fs1>.
AT NEW tdid.
REFRESH li_thead.
REFRESH li_line.
li_thead-tdid = <fs1>-tdid.
APPEND li_thead.
ENDAT.
li_line-tdline = <fs1>-tdline.
APPEND li_line.
AT END OF tdid.
CALL FUNCTION 'SAVE_TEXT'
EXPORTING
header = li_thead
savemode_direct = 'X'
TABLES
lines = li_line
ENDAT.
ENDLOOP.
Assuming that the table is sorted by TDID and no field left of TDID changes more frequently than TDID:
LOOP AT lines ASSIGNING <fs1>.
AT NEW tdid.
REFRESH some_other_tab.
ENDAT.
APPEND <fs1> TO some_other_tab.
AT END OF tdid.
CALL FUNCTION ...
ENDAT.
ENDLOOP.
The unpredictability as mentioned by vwegert comes because the characters fields next to the field on which Control statement is applied are converted to asterisks(*). If you want to use these values in the control statement make sure you copy the values in a temporary table and loop on it instead of the original internal table and use the values using READ on the original internal table. Also keep in mind that control statement considers all columns to the left of the column being used in the statement for it's condition.

Problems with writing to a MS Access Database (Delphi)

I'm trying to write bits of code to a Microsoft access database from Delphi. I'm getting data from a TStringGrid. The first column has the ItemID, and the 2nd column has the Quantity. I'd like it to loop through the TStringGrid and save each row as a reperate row in my database and also save the Order ID with it on every column (The order ID stays the same for each order so that doesn't need to change) .
I'm getting an error when running which says
"Project Heatmat.exe raised an exception class EVarientInvalidArgError with message 'Invalid Argument'. Process Stopped."
I can't figure out why it's giving me this error, and as you can probably see i'm not very good at coding yet. Any help would be appreciated!
Thank you.
procedure TCreateNewOrder.btnSaveClick(Sender: TObject);
var
intNumber, count : integer;
begin
Count:= 0;
if messagedlg ('Are you sure?', mtWarning, [mbyes, mbno], 0) = mryes then
begin
with HeatmatConnection.HeatmatDatabase do
begin
intNumber:= TBLOrder.RecordCount;
TBLOrder.Append;
TBLOrder['CustomerID']:= CompanyName.ItemIndex+1;
TBLOrder['OrderID']:= intNumber +1;
for count:= 1 to StringGrid1.RowCount-1 do
begin
TBLOrderedItem.Append;
TBLOrderedItem['OrderID']:= intNumber+1;
TBLOrderedItem['ItemID']:= StringGrid1.Cells[1, count];
TBLOrderedItem['Quantity']:= StringGrid1.Cells[2, count];
TBLOrderedItem.Post;
end;
end;
end;
end;
TStringGrid cells are strings. trying to assign a string directly to a numeric field will raise an Exception.
So a good practice is to assign values to database fields via AsString, AsInteger, AsBoolean etc... this will make the correct conversion.
In your code use:
TBLOrderedItem.FieldByName('ItemID').AsString := StringGrid1.Cells[1, count];
The same is true for Quantity.
To assign an Integer value use:
TBLOrderedItem.FieldByName('OrderID').AsInteger := intNumber + 1;
BTW, you are forgetting TBLOrder.Post i.e:
....
TBLOrder.Append;
TBLOrder.FieldByName('CustomerID').AsInteger := CompanyName.ItemIndex + 1;
TBLOrder.FieldByName('OrderID').AsInteger := intNumber + 1;
TBLOrder.Post;
...
Finally, I would also suggest to rename TBLOrder to tblOrder so that it's name wont imply that it is a Type.

Resources