Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/27/18 in all areas

  1. i had the same problem with my custom css when i updated my project from 1.0 to 1.5 version : for resum : before (with 1.0 version and extjs 4): x-grid-row-selected , x-grid-row-...... after (with 1.5 version and extjs 6) : x-grid-item-selected, x-grid-item-......
    1 point
  2. You can try this: CustomCSS: .custom-grid .x-grid-item-focused .x-grid-cell-inner:before { border: none !important; } ... and UniEvents: function beforeInit(sender, config) { config.cls = 'custom-grid'; }
    1 point
  3. For people who is having problems with download the zip file. UExportExcel.pas //============================================================================= // TDataSet to Excel without OLE or Excel required // Mike Heydon Dec 2002 // Adapted to Unigui with TUniDBGrid // Mauricio Naozuka - 26/04/2018 - naozuka@gmail.com //============================================================================= unit UExportExcel; // Example // // Add uses UExportExcel // //procedure TMainForm.UniButton1Click(Sender: TObject); //var url, filename, reportname : String; // exportExcel: TDataSetToExcel; // i: integer; //begin // reportname := 'ExcelReport'; // url := UniServerModule.LocalCacheURL+name+'.xls'; // filename := UniServerModule.NewCacheFileUrl(false, 'xls', reportname, '', url); // // exportExcel := TDataSetToExcel.Create; // exportExcel.WriteFile(filename, UniDBGrid1); // FreeAndNil(exportExcel); // UniSession.SendFile(filename, reportname+'.xls'); //end; interface uses Windows, SysUtils, DB, Math, uniBasicGrid, uniDBGrid; type // TDataSetToExcel TDataSetToExcel = class(TObject) protected procedure WriteToken(AToken: word; ALength: word); procedure WriteFont(const AFontName: Ansistring; AFontHeight, AAttribute: word); procedure WriteFormat(const AFormatStr: Ansistring); private FRow: word; FFieldCount: integer; FDataFile: file; FFileName: string; public constructor Create; function WriteFile(const AFileName: string; const AGrid: TUniDBGrid): boolean; end; //----------------------------------------------------------------------------- implementation const // XL Tokens XL_DIM = $00; XL_BOF = $09; XL_EOF = $0A; XL_DOCUMENT = $10; XL_FORMAT = $1E; XL_COLWIDTH = $24; XL_FONT = $31; // XL Cell Types XL_INTEGER = $02; XL_DOUBLE = $03; XL_STRING = $04; // XL Cell Formats XL_INTFORMAT = $81; XL_DBLFORMAT = $82; XL_XDTFORMAT = $83; XL_DTEFORMAT = $84; XL_TMEFORMAT = $85; XL_HEADBOLD = $40; XL_HEADSHADE = $F8; // ======================== // Create the class // ======================== constructor TDataSetToExcel.Create; begin FFieldCount := 0; end; // ==================================== // Write a Token Descripton Header // ==================================== procedure TDataSetToExcel.WriteToken(AToken: word; ALength: word); var aTOKBuffer: array[0..1] of word; begin aTOKBuffer[0] := AToken; aTOKBuffer[1] := ALength; Blockwrite(FDataFile, aTOKBuffer, SizeOf(aTOKBuffer)); end; // ==================================== // Write the font information // ==================================== procedure TDataSetToExcel.WriteFont(const AFontName: ansistring; AFontHeight, AAttribute: word); var iLen: byte; begin AFontHeight := AFontHeight * 20; WriteToken(XL_FONT, 5 + length(AFontName)); BlockWrite(FDataFile, AFontHeight, 2); BlockWrite(FDataFile, AAttribute, 2); iLen := length(AFontName); BlockWrite(FDataFile, iLen, 1); BlockWrite(FDataFile, AFontName[1], iLen); end; // ==================================== // Write the format information // ==================================== procedure TDataSetToExcel.WriteFormat(const AFormatStr: ansistring); var iLen: byte; begin WriteToken(XL_FORMAT, 1 + length(AFormatStr)); iLen := length(AFormatStr); BlockWrite(FDataFile, iLen, 1); BlockWrite(FDataFile, AFormatStr[1], iLen); end; // ==================================== // Write the XL file from data set // ==================================== function TDataSetToExcel.WriteFile(const AFilename:String; const AGrid: TUniDBGrid): boolean; var bRetvar: boolean; aDOCBuffer: array[0..1] of word; aDIMBuffer: array[0..3] of word; aAttributes: array[0..2] of byte; i: integer; iColNum, iDataLen: byte; sStrData: string; fDblData: double; wWidth: word; sStrBytes: TBytes; begin if not Assigned(AGrid) then raise Exception.Create('There is no Grid is vinculated.'); if not Assigned(AGrid.DataSource) then raise Exception.Create('There is no DataSource is vinculated to Grid ' + AGrid.Name); if not Assigned(AGrid.DataSource.DataSet) then raise Exception.Create('There is no DataSet is vinculated to DataSource ' + AGrid.DataSource.Name); bRetvar := true; FRow := 0; FillChar(aAttributes, SizeOf(aAttributes), 0); FFileName := ChangeFileExt(AFilename, '.xls'); AssignFile(FDataFile, FFileName); try Rewrite(FDataFile, 1); // Beginning of File WriteToken(XL_BOF, 4); aDOCBuffer[0] := 0; aDOCBuffer[1] := XL_DOCUMENT; Blockwrite(FDataFile, aDOCBuffer, SizeOf(aDOCBuffer)); // Font Table WriteFont('Arial', 10, 0); WriteFont('Arial', 10, 1); //WriteFont('Courier New', 11, 0); // Column widths iColNum := 0; for i := 0 to AGrid.Columns.Count-1 do begin if not AGrid.Columns[i].Visible then continue; if AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).DisplayWidth + 1 > Length(AGrid.Columns[i].Title.Caption) then begin wWidth := (AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).DisplayWidth + 1) * 256; end else begin wWidth := (Length(AGrid.Columns[i].Title.Caption) + 1) * 256; end; // Limitar o tamanho da coluna if wWidth > 80*256 then wWidth := 80*256; // if AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).DataType = ftDateTime then // inc(wWidth, 100); // if AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).DataType = ftDate then // inc(wWidth, 1050); // if AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).DataType = ftTime then // inc(wWidth, 100); WriteToken(XL_COLWIDTH, 4); BlockWrite(FDataFile, iColNum, 1); BlockWrite(FDataFile, iColNum, 1); BlockWrite(FDataFile, wWidth, 2); Inc(iColNum); end; FFieldCount := iColNum; // Column Formats WriteFormat('Geral'); WriteFormat('0'); WriteFormat('#.##0,0000'); WriteFormat('dd/mm/aaaa hh:mm:ss'); WriteFormat('dd/mm/aaaa'); WriteFormat('hh:mm:ss'); // Dimensions WriteToken(XL_DIM, 8); aDIMBuffer[0] := 0; aDIMBuffer[1] := Min(AGrid.DataSource.DataSet.RecordCount, $FFFF); aDIMBuffer[2] := 0; aDIMBuffer[3] := Min(FFieldCount - 1, $FFFF); Blockwrite(FDataFile, aDIMBuffer, SizeOf(aDIMBuffer)); // Column Headers iColNum := 0; for i := 0 to AGrid.Columns.Count-1 do begin if not AGrid.Columns[i].Visible then continue; // sStrData := FDataSet.Fields[i].DisplayName; sStrBytes := TEncoding.ANSI.GetBytes(AGrid.Columns[i].Title.Caption); iDataLen := length(sStrBytes); WriteToken(XL_STRING, iDataLen + 8); WriteToken(FRow, iColNum); aAttributes[1] := XL_HEADBOLD; //aAttributes[2] := XL_HEADSHADE; BlockWrite(FDataFile, aAttributes, SizeOf(aAttributes)); BlockWrite(FDataFile, iDataLen, SizeOf(iDataLen)); if iDataLen > 0 then BlockWrite(FDataFile, sStrBytes[0], iDataLen); aAttributes[2] := 0; Inc(iColNum); end; try AGrid.DataSource.DataSet.DisableControls; AGrid.DataSource.DataSet.First; // Data Rows while not AGrid.DataSource.DataSet.Eof do begin inc(FRow); iColNum := 0; for i := 0 to AGrid.Columns.Count-1 do begin if not AGrid.Columns[i].Visible then continue; case AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).DataType of ftBoolean, ftWideString, ftFixedChar, ftString: begin try // sStrData := FDataSet.Fields[i].AsString; sStrBytes:=TEncoding.ANSI.GetBytes(AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).AsString); iDataLen := length(sStrBytes); WriteToken(XL_STRING, iDataLen + 8); WriteToken(FRow, iColNum); aAttributes[1] := 0; BlockWrite(FDataFile, aAttributes, SizeOf(aAttributes)); BlockWrite(FDataFile, iDataLen, SizeOf(iDataLen)); if iDataLen > 0 then BlockWrite(FDataFile, sStrBytes[0], iDataLen); except on E: Exception do //ShowMessage(E.Message); raise Exception.Create('Erro Converter: ' + E.Message); end; end; ftAutoInc, ftSmallInt, ftInteger, ftWord, ftLargeInt: begin try fDblData := AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).AsFloat; iDataLen := SizeOf(fDblData); WriteToken(XL_DOUBLE, 15); WriteToken(FRow, iColNum); aAttributes[1] := XL_INTFORMAT; BlockWrite(FDataFile, aAttributes, SizeOf(aAttributes)); BlockWrite(FDataFile, fDblData, iDatalen); except on E: Exception do //ShowMessage(E.Message); raise Exception.Create('Erro Converter Inteiro: ' + E.Message); end; end; ftFloat, ftCurrency, ftBcd, ftFMTBcd: begin try fDblData := AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).AsFloat; iDataLen := SizeOf(fDblData); WriteToken(XL_DOUBLE, 15); WriteToken(FRow, iColNum); aAttributes[1] := XL_DBLFORMAT; BlockWrite(FDataFile, aAttributes, SizeOf(aAttributes)); BlockWrite(FDataFile, fDblData, iDatalen); except on E: Exception do //ShowMessage(E.Message); raise Exception.Create('Erro Converter Float: ' + E.Message); end; end; ftDateTime: begin try if not AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).IsNull then begin fDblData := AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).AsFloat; iDataLen := SizeOf(fDblData); WriteToken(XL_DOUBLE, 15); WriteToken(FRow, iColNum); aAttributes[1] := XL_XDTFORMAT; BlockWrite(FDataFile, aAttributes, SizeOf(aAttributes)); BlockWrite(FDataFile, fDblData, iDatalen); end; except on E: Exception do //ShowMessage(E.Message); raise Exception.Create('Erro Converter DateTime: ' + E.Message); end; end; ftDate: begin try if not AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).IsNull then begin fDblData := AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).AsFloat; iDataLen := SizeOf(fDblData); WriteToken(XL_DOUBLE, 15); WriteToken(FRow, iColNum); aAttributes[1] := XL_DTEFORMAT; BlockWrite(FDataFile, aAttributes, SizeOf(aAttributes)); BlockWrite(FDataFile, fDblData, iDatalen); end; except on E: Exception do //ShowMessage(E.Message); raise Exception.Create('Erro Converter Date: ' + E.Message); end; end; ftTime: begin try if not AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).IsNull then begin fDblData := AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).AsFloat; iDataLen := SizeOf(fDblData); WriteToken(XL_DOUBLE, 15); WriteToken(FRow, iColNum); aAttributes[1] := XL_TMEFORMAT; BlockWrite(FDataFile, aAttributes, SizeOf(aAttributes)); BlockWrite(FDataFile, fDblData, iDatalen); end; except on E: Exception do //ShowMessage(E.Message); raise Exception.Create('Erro Converter Time: ' + E.Message); end; end; ftMemo: begin // Does not print memo end; else raise Exception.Create('Tipo [' + AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).ClassName + '] do campo [' + AGrid.DataSource.DataSet.FieldByName(AGrid.Columns[i].FieldName).FieldName + '] não foi tratado.'); end; Inc(iColNum); end; // end of for AGrid.DataSource.DataSet.Next; end; // end of while finally AGrid.DataSource.DataSet.EnableControls; AGrid.DataSource.DataSet.First; end; // End of File WriteToken(XL_EOF, 0); CloseFile(FDataFile); except bRetvar := false; end; Result := bRetvar; end; end.
    1 point
  4. Theoretically, there is no limit to number of sessions that a uniGUI server might serve. The only limit is system resources. However, in a real life scenario various factors may limit this. From what I can see, the average number of concurrent users on a typical uniGUI application developed for a closed network is around a few hundreds (maybe even less around 50 -100). Regarding your concerns, we are working on a new server technology for uniGUI to address such scenarios. It is called uniGUI HyperServer and it is currently beta. HyperServer is an internal load balancer which will distribute sessions among multiple internal processes. These processes are called nodes. HyperServer will also enable remote deployment for your applications. You will be able to upgrade your binaries from a remote location and without a need to restart your server. Regarding resource consumption, it is really related to your application design and optimization level. If you can optimize your session's memory usage, you'll be able to increase number of concurrent sessions dramatically. Again, you need to make sure that your DB backend is also scalable. Next step for HyperServer will be implementation of an inter-server load balancer. This will enable you to deploy your uniGUI apps in a server-farm. ... ... ...
    1 point
  5. Hi all, as far as I have read from the forum the only way to deal with big datasets and uniDbGrids is paging. This works quite well, but I would prefer another option, let me explain better. Without paging, the web server fetches the whole dataset and it gives back it to the client: DB server --> Web server (Unigui) : whole dataset Web Server (UniGUI) --> Browser: whole dataset This is the worst situation, as it implies a lot of overhead for all the actors (DB Server, Web Server, Browser, network, etc.). It should not be used for large datasets. With paging, the web server fetches the whole dataset (this is why the option FetchAll shall be set), and it gives back to the client (browser) just the current page. Therefore: DB server --> Web server (Unigui) : whole dataset Web Server (UniGUI) --> Browser: partial dataset/ curent page This is better, as it minimizes the overhead on the client side (browser), but the Web Server (UniGUI) still has to deal with a large dataset that has to be fetched entirely from the DB server and to be kept in memory. The last option, that I really miss with UniGUI, is the way that VCL DBGrid works, but it is common to find it on many websites. This is the reason why I'm asking about it, I'm confident there should be a way to work it out with UniGUI.I think that it could be called "incremental fetch". Practically, UniGUI should fetch just the first N rows and show them on the UniDbGrid component, letting the user know that there are more rows than the ones actually visible. It could be a button on the paging bar called "Load more rows". If the user clicks on that button, UniGUI should fetch N additional rows from the dataset, and then display N*2 total rows. This approach can be iterated till the whole dataset is fetched. Alternatively, without using the "Load more rows" button, it could be possible to do it in the VCL way: when the user scrolls down the grid and he reaches the last line, the "give me more lines" could be automatically fired. The "incremental fetch" solution would be the best in my opinion, as the user does not really care to know the number of pages in the grid, nor he needs to skip randonly on different pages. Usually he does want quickly the first N rows, and then the possibility to look up another N rows for a fe times. Then, if the data is not found, he would change the actual filter/selection. This would bring the following situation: DB server --> Web server (Unigui) : partial dataset Web Server (UniGUI) --> Browser: partial dataset Sorry for the long post, hoping that I was clear, thank you all. Andrea
    1 point
×
×
  • Create New...