Announcement
ABCFeatured Content
Recent Activity
LIM: Example of Register Field Population from a File Explorer File 1
DISCLAIMER: It should be noted that the focus of this technical guide is to provide general information, considerations, and guidelines for an identified topic. It is NOT to be interpreted as the ONLY approach nor a guarantee that there will not be any issues encountered by using this approach as a customer’s requirements or application configuration may render this guidance as not applicable. In addition, statements that “we believe” and similar statements reflect our beliefs and opinions on the relevant subject. These statements are based upon information available to us as of the date of this article, and while we believe such information forms a reasonable basis for such statements, such information may be limited or incomplete, and our statements should not be read to indicate that we have conducted an exhaustive inquiry into, or review of, all potentially available relevant information. OneStream does not warrant as to the accuracy of this guidance, which is provided on an as-is basis. Any forward-looking statements contained herein are based on information available at the time those statements are made and/or good faith beliefs and assumptions as of that time with respect to future events and are subject to risks and uncertainties that could cause actual performance or results to differ materially from those expressed in or suggested by the forward-looking statements. Considering these risks and uncertainties, the forward-looking events and circumstances discussed in this guide may not occur and actual results could differ materially from those anticipated or implied in the forward-looking statements. VERSION: PV900 SV200 PLATFORM: 9.2.0 USE CASE: your customer wants a standard repository to store supplementary information to be used to populate certain Register Fields. In this example, a list of job codes and its descriptions is handled as a Spreadsheet component within an OneStream dashboard. Every time a user selects a job code or inputs a job code in the Register, the expectation is that the Job Code Description register field is populated with the description that is from this .csv. PURPOSE: to provide you with an example that you can leverage as part of your build, whether you decide to incorporate this to existing input options (Register, Spreadsheet, Import File, Connector). NOTE(S): my example assumes that this file is a .csv and placed in a dedicated folder in File Explorer. ASSUMPTIONS: The relevant Register Fields have already been created. In my example, I have JobCode and JobCodeDescription register fields. The .csv is uploaded to a dedicated folder in File Explorer A simple dashboard that allows the Administrator or select users to update the file. File Source Type for the Spreadsheet component is set up to reference Application Database File. I will be splitting this approach into two articles - 1 which will cover WsComponentService, 2 which will cover WorkforcePlanningImportRegisterConnector, WsDynamicGridService and WsTableViewService. A) WsComponentService: ImportRegisterData (to handle importing files) Example logic to handle populating the JobCodeDescription for WsComponentService: NOTE: I am putting in a sample code equivalent below which pertains to SV200 as the table names have changed from PLN to LIM. private static void populateJobCodeDesc2(SessionInfo si, BRGlobals brGlobals, DashboardWorkspace workspace, DashboardExtenderArgs args, XFSelectionChangedTaskResult taskResult) { int rowNumber = 0; var errorList = new List<string>(); var invalidJobCodes = new List<string>(); try { // Load register rows once DataTable registerRows = GetRegisterRows(si); // Load lookup file once into memory (cached dictionary) FileSystemLocation location = FileSystemLocation.ApplicationDatabase; string fileFullName = "Documents/Public/PLP_Lookups/JobCodeLookup.csv"; bool includeContentFileBytes = true; bool failGracefully = true; XFFileEx sourceFile = BRApi.FileSystem.GetFile(si, location, fileFullName, includeContentFileBytes, failGracefully); if (sourceFile == null || sourceFile.XFFile == null || sourceFile.XFFile.ContentFileBytes == null) { throw new XFException(si, new Exception($"Source file '{fileFullName}' could not be loaded or is empty.")); } // Convert byte[] to string using UTF8 string textContent = System.Text.Encoding.UTF8.GetString(sourceFile.XFFile.ContentFileBytes); // Split into lines (keep non-empty lines) string[] lines = textContent.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); char delimiter = DetectDelimiter(lines); Dictionary<string, string=""> jobCodeLookup = BuildJobCodeLookup(lines, delimiter); // Batch SQL updates (avoid ExecuteSql per row) // Chunk updates to prevent excessively large SQL strings const int batchSize = 500; int statementsInBatch = 0; var sqlBatch = new System.Text.StringBuilder(capacity: 64 * 1024); var connInfo = BRApi.Database.CreateApplicationDbConnInfo(si); foreach (DataRow regRow in registerRows.Rows) { rowNumber++; string jcName = regRow["JobCode"]?.ToString()?.Trim() ?? string.Empty; string empId = regRow["EmployeeID"]?.ToString()?.Trim() ?? string.Empty; string jcDescription; if (!string.IsNullOrEmpty(jcName) && jobCodeLookup.TryGetValue(jcName, out jcDescription)) { regRow["JobCodeDescription"] = jcDescription ?? string.Empty; } else { jcDescription = "INVALID JOB CODE"; if (!string.IsNullOrEmpty(jcName)) invalidJobCodes.Add(jcName); errorList.Add($"Row {rowNumber}, EmployeeID {empId}, JobCode '{jcName}': INVALID JOB CODE"); } // Escape for SQL safety string escDesc = SqlStringHelper.EscapeSqlString(jcDescription); string escJc = SqlStringHelper.EscapeSqlString(jcName); string escEmp = SqlStringHelper.EscapeSqlString(empId); // If your staging table has a unique row key (recommended), use that instead. sqlBatch.AppendLine($@" UPDATE [limb2].XFW_LIM_StageRegister SET JobCodeDescription = '{escDesc}' WHERE EmployeeID = '{escEmp}' AND JobCode = '{escJc}';"); statementsInBatch++; // Execute in chunks if (statementsInBatch >= batchSize) { BRApi.Database.ExecuteSql(connInfo, sqlBatch.ToString(), false); sqlBatch.Clear(); statementsInBatch = 0; } } if (statementsInBatch > 0) { BRApi.Database.ExecuteSql(connInfo, sqlBatch.ToString(), false); } // If any invalids, throw a consolidated error (after updates are done) if (errorList.Count > 0) { string errorMessage = "Some JobCodes were marked as INVALID:" + Environment.NewLine + string.Join(Environment.NewLine, errorList); throw new XFException(si, new Exception(errorMessage)); } } catch (XFException) { throw; } catch (Exception ex) { throw new XFException(si, new Exception("Unexpected error occurred: " + ex.Message, ex)); } }</string,></string></string> IMPORTANT NOTE: If you have more customizations, then you will need to assess how many of these customizations rely on fetching the register rows. You want to consider fetching these register rows once and reuse it instead of having each method (which corresponds to a different customization) call it; this is to optimize performance and processing. You may want to also consider the use of helpers. Below are some helpers that were referenced in the code above. GetRegisterRows private static DataTable GetRegisterRows(SessionInfo si) { try { var sql = new System.Text.StringBuilder(); sql.AppendLine($@" SELECT [limb2].XFW_LIM_StageRegister.EmployeeID, [limb2].XFW_LIM_StageRegister.Instance, [limb2].XFW_LIM_StageRegister.LastName, [limb2].XFW_LIM_StageRegister.FirstName, [limb2].XFW_LIM_StageRegister.Status, [limb2].XFW_LIM_StageRegister.HireDate, [limb2].XFW_LIM_StageRegister.HirePeriod, [limb2].XFW_LIM_StageRegister.TermDate, [limb2].XFW_LIM_StageRegister.TermPeriod, [limb2].XFW_LIM_StageRegister.Salary, [limb2].XFW_LIM_StageRegister.SalaryOverride, [limb2].XFW_LIM_StageRegister.Entity, [limb2].XFW_LIM_StageRegister.CostCenter, [limb2].XFW_LIM_StageRegister.CostCenterDescription, [limb2].XFW_LIM_StageRegister.JobCode, [limb2].XFW_LIM_StageRegister.JobCodeDescription, [limb2].XFW_LIM_StageRegister.FTE, [limb2].XFW_LIM_StageRegister.HireYear, [limb2].XFW_LIM_StageRegister.TermYear FROM [limb2].XFW_LIM_StageRegister "); using (DbConnInfo dbConnApp = BRApi.Database.CreateApplicationDbConnInfo(si)) { DataTable dt = BRApi.Database.ExecuteSql(dbConnApp, sql.ToString(), false); return dt; } } catch (Exception ex) { throw ErrorHandler.LogWrite(si, new XFException(si, ex)); } } DetectDelimiter private static char DetectDelimiter(string[] lines) { // Default comma; inspect the first non-empty line foreach (var ln in lines) { var line = ln?.Trim(); if (string.IsNullOrEmpty(line)) continue; // Prefer tab/semicolon/pipe if present if (line.Contains("\t")) return '\t'; if (line.Contains(";")) return ';'; if (line.Contains("|")) return '|'; return ','; // default } return ','; // fallback } BuildJobCodeLookup private static Dictionary<string, string=""> BuildJobCodeLookup(string[] lines, char delimiter) { var dict = new Dictionary<string, string="">(StringComparer.OrdinalIgnoreCase); bool headerSkipped = false; foreach (string raw in lines) { string line = raw?.Trim(); if (string.IsNullOrEmpty(line)) continue; // Parse respecting quotes var fields = ParseDelimitedLine(line, delimiter); if (fields.Count < 2) continue; string code = (fields[0] ?? string.Empty).Trim(); string desc = (fields[1] ?? string.Empty).Trim(); // Skip header row once if it looks like a header // (common: "JobCode,JobCodeDesc" or similar) if (!headerSkipped && LooksLikeHeader(code, desc)) { headerSkipped = true; continue; } if (string.IsNullOrEmpty(code)) continue; // First occurrence wins (avoid overwrite) if (!dict.ContainsKey(code)) dict[code] = desc; } return dict; }</string,></string,> LooksLikeHeader private static bool LooksLikeHeader(string first, string second) { string a = (first ?? string.Empty).Trim(); string b = (second ?? string.Empty).Trim(); // Minimal header detection: common names return a.Equals("JobCode", StringComparison.OrdinalIgnoreCase) || a.Equals("Job Code", StringComparison.OrdinalIgnoreCase) || b.Equals("JobCodeDesc", StringComparison.OrdinalIgnoreCase) || b.Equals("Job Code Desc", StringComparison.OrdinalIgnoreCase) || b.Equals("JobCodeDescription", StringComparison.OrdinalIgnoreCase); } ParseDelimitedLine private static List<string> ParseDelimitedLine(string line, char delimiter) { var result = new List<string>(8); if (line == null) { result.Add(string.Empty); return result; } var sb = new System.Text.StringBuilder(); bool inQuotes = false; for (int i = 0; i < line.Length; i++) { char c = line[i]; if (c == '"') { // If we're in quotes and next char is also quote, it's an escaped quote if (inQuotes && i + 1 < line.Length && line[i + 1] == '"') { sb.Append('"'); i++; // skip next quote } else { inQuotes = !inQuotes; } continue; } if (c == delimiter && !inQuotes) { result.Add(sb.ToString()); sb.Clear(); continue; } sb.Append(c); } result.Add(sb.ToString()); return result; }</string></string> NOTE: if you plan to use StringBuilder() instead of declaring the variable as a string, you will need to import System.Text into the file. StringBuilder() is a method group so it will also have to be referenced as sql.ToString() as part of the BRApi.Database.ExecuteSql line. Example of what I mean by “import” below. File Explorer Part 2jzhang3 hours agoOneStream Employee22Views0likes0CommentsLIM: Example of Register Field Population from a File Explorer File 2
DISCLAIMER: It should be noted that the focus of this technical guide is to provide general information, considerations, and guidelines for an identified topic. It is NOT to be interpreted as the ONLY approach nor a guarantee that there will not be any issues encountered by using this approach as a customer’s requirements or application configuration may render this guidance as not applicable. In addition, statements that “we believe” and similar statements reflect our beliefs and opinions on the relevant subject. These statements are based upon information available to us as of the date of this article, and while we believe such information forms a reasonable basis for such statements, such information may be limited or incomplete, and our statements should not be read to indicate that we have conducted an exhaustive inquiry into, or review of, all potentially available relevant information. OneStream does not warrant as to the accuracy of this guidance, which is provided on an as-is basis. Any forward-looking statements contained herein are based on information available at the time those statements are made and/or good faith beliefs and assumptions as of that time with respect to future events and are subject to risks and uncertainties that could cause actual performance or results to differ materially from those expressed in or suggested by the forward-looking statements. Considering these risks and uncertainties, the forward-looking events and circumstances discussed in this guide may not occur and actual results could differ materially from those anticipated or implied in the forward-looking statements. VERSION: PV900 SV200 PLATFORM: 9.2.0 USE CASE: your customer wants a standard repository to store supplementary information to be used to populate certain Register Fields. In this example, a list of job codes and its descriptions is handled as a Spreadsheet component within an OneStream dashboard. Every time a user selects a job code or inputs a job code in the Register, the expectation is that the Job Code Description register field is populated with the description that is from this .csv. PURPOSE: to provide you with an example that you can leverage as part of your build, whether you decide to incorporate this to existing input options (Register, Spreadsheet, Import File, Connector). NOTE(S): my example assumes that this file is a .csv and placed in a dedicated folder in File Explorer. ASSUMPTIONS: The relevant Register Fields have already been created. In my example, I have JobCode and JobCodeDescription register fields. The .csv is uploaded to a dedicated folder in File Explorer A simple dashboard that allows the Administrator or select users to update the file. File Source Type for the Spreadsheet component is set up to reference Application Database File. I will be splitting this approach into two articles - 1 which will cover WsComponentService, 2 which will cover WorkforcePlanningImportRegisterConnector, WsDynamicGridService and WsTableViewService. B) WorkforcePlanningImportRegisterConnector#*: ImportRegisterData (to handle connector) *Business rule name may be different depending on the LIM selection and number of workspaces created. Before: this is before any customizations. This is what your ImportRegisterData should start out as. After: example of how it could be re-arranged to handle customizations that rely on fetching register rows. Assuming that there are multiple customizations, the below is an example to handle populating the job code description for WorkforcePlanningImportRegisterConnector#*: NOTE: I am putting in a sample code equivalent below which pertains to SV200 as the table names have changed from PLN to LIM. private static void populateJobCodeDesc2(SessionInfo si, BRGlobals brGlobals, DashboardExtenderArgs args, DataTable registerRows) { var errorList = new List<string>(); var invalidJobCodes = new HashSet<string>(StringComparer.OrdinalIgnoreCase); try { // Load the file from file explorer into memory FileSystemLocation location = FileSystemLocation.ApplicationDatabase; string fileFullName = "Documents/Public/PLP_Lookups/JobCodeLookup.csv"; bool includeContentFileBytes = true; bool failGracefully = true; XFFileEx sourceFile = BRApi.FileSystem.GetFile(si, location, fileFullName, includeContentFileBytes, failGracefully); if (sourceFile == null || sourceFile.XFFile == null || sourceFile.XFFile.ContentFileBytes == null) { throw new XFException(si, new Exception($"Source file '{fileFullName}' could not be loaded or is empty.")); } // Convert byte[] to string using UTF8 string textContent = System.Text.Encoding.UTF8.GetString(sourceFile.XFFile.ContentFileBytes); // Split into lines string[] lines = textContent.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); // Detect delimiter from the first line char delimiter = ','; if (lines.Length > 0) { string firstLine = lines[0]; if (firstLine.Contains("\t")) delimiter = '\t'; else if (firstLine.Contains(";")) delimiter = ';'; else if (firstLine.Contains("|")) delimiter = '|'; // Default stays as comma } // Parse file into dictionary: JobCode -> JobCodeDesc Dictionary<string, string=""> jobCodeLookup = new Dictionary<string, string="">(StringComparer.OrdinalIgnoreCase); foreach (string line in lines) { string[] parts = line.Split(delimiter); if (parts.Length >= 2) { string code = parts[0].Trim(); string desc = parts[1].Trim(); if (!jobCodeLookup.ContainsKey(code)) { jobCodeLookup[code] = desc; } } } // Process register rows using var dbConn = BRApi.Database.CreateApplicationDbConnInfo(si); int rowNumber = 0; foreach (DataRow regRow in registerRows.Rows) { rowNumber++; string jcName = regRow["JobCode"].ToString(); string empId = regRow["EmployeeID"].ToString(); string jcDescription; if (jobCodeLookup.TryGetValue(jcName, out string desc)) { jcDescription = desc; } else { jcDescription = "INVALID JOB CODE"; invalidJobCodes.Add(jcName); errorList.Add($"Row {rowNumber}, EmployeeID {empId}, JobCode '{jcName}': INVALID JOB CODE"); } // Update staging table string updateSql = $@" UPDATE [limb2].XFW_LIM_StageRegister SET JobCodeDescription = '{SqlStringHelper.EscapeSqlString(jcDescription)}' WHERE JobCode = '{SqlStringHelper.EscapeSqlString(jcName)}'; "; BRApi.Database.ExecuteSql(dbConn, updateSql, false); } // Report invalids if any if (errorList.Count > 0) { string errorMessage = "Some JobCodes were marked as INVALID:" + Environment.NewLine + string.Join(Environment.NewLine, errorList); throw new XFException(si, new Exception(errorMessage)); } } catch (Exception ex) { throw ErrorHandler.LogWrite(si, new XFException(si, ex)); } }</string,></string,></string></string> NOTE: if you plan to use StringBuilder() instead of declaring the variable as a string in your WorkforcePlanningImportRegisterConnector#* rule, you will need to import System.Text into the business rule. StringBuilder() is a method group so it will also have to be referenced as sql.ToString() as part of the BRApi.Database.ExecuteSql line. Example of what I mean by “import” below. C) WsDynamicGridService: Register Below is an example of how I arranged my logic within my BeforeEvent. The below is an example of the logic associated with populateJobCodeDesc2. NOTE: I am putting in a sample code equivalent below for WsDynamicGridService. private static void populateJobCodeDesc2(SessionInfo si, DashboardDynamicGridArgs args) { List<string> invalidJobCodes = new List<string>(); // Load the file from file explorer into memory FileSystemLocation location = FileSystemLocation.ApplicationDatabase; string fileFullName = "Documents/Public/PLP_Lookups/JobCodeLookup.csv"; bool includeContentFileBytes = true; bool failGracefully = true; XFFileEx sourceFile = BRApi.FileSystem.GetFile(si, location, fileFullName, includeContentFileBytes, failGracefully); if (sourceFile == null || sourceFile.XFFile == null || sourceFile.XFFile.ContentFileBytes == null) { throw new XFException(si, new Exception($"Source file '{fileFullName}' could not be loaded or is empty.")); } // Convert byte[] to string using UTF8 string textContent = System.Text.Encoding.UTF8.GetString(sourceFile.XFFile.ContentFileBytes); // Split into lines string[] lines = textContent.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); // Detect delimiter from the first line char delimiter = ','; if (lines.Length > 0) { string firstLine = lines[0]; if (firstLine.Contains("\t")) delimiter = '\t'; else if (firstLine.Contains(";")) delimiter = ';'; else if (firstLine.Contains("|")) delimiter = '|'; // Default stays as comma } // Parse file into dictionary: JobCode -> JobCodeDesc Dictionary<string, string=""> jobCodeLookup = new Dictionary<string, string="">(StringComparer.OrdinalIgnoreCase); foreach (string line in lines) { string[] parts = line.Split(delimiter); if (parts.Length >= 2) { string code = parts[0].Trim(); string desc = parts[1].Trim(); if (!jobCodeLookup.ContainsKey(code)) { jobCodeLookup[code] = desc; } } } // now process the edited rows if (args.SaveDataArgs != null) { foreach (XFEditedDataRow row in args.SaveDataArgs.EditedDataRows) { if (row.InsertUpdateOrDelete != DbInsUpdateDelType.Update) continue; string jcName = row.ModifiedDataRow.Items["JobCode"].ToString(); string empId = row.ModifiedDataRow.Items["EmployeeID"].ToString(); string jcDescription = null; try { if (jobCodeLookup.TryGetValue(jcName, out jcDescription)) { row.ModifiedDataRow.Items["JobCodeDescription"] = jcDescription; } else { // Not found in file = invalid job code invalidJobCodes.Add($"EmployeeID {empId}, JobCode {jcName}"); row.ModifiedDataRow.Items["JobCodeDescription"] = null; } } catch { // Any exception = treat as invalid invalidJobCodes.Add($"EmployeeID {empId}, JobCode {jcName}"); row.ModifiedDataRow.Items["JobCodeDescription"] = null; } } } if (invalidJobCodes.Count > 0) { string errorMessage = "Invalid job codes detected:" + Environment.NewLine + string.Join(Environment.NewLine, invalidJobCodes); throw new XFException(si, new Exception(errorMessage)); } }</string,></string,></string></string> D) WsTableViewService: Spreadsheet Below is an example of how I arranged my logic within my BeforeEvent. The below is an example of the populateJobCodeDesc2 logic. It is important to only process rows with the valid information so I have a section to identify which rows to skip. NOTE: I am putting in a sample code equivalent below for WsTableViewService. private static void populateJobCodeDesc2(SessionInfo si, BRGlobals brGlobals, DashboardWorkspace workspace, TableView tableView) { List<string> invalidJobCodes = new List<string>(); // Load the file from file explorer into memory FileSystemLocation location = FileSystemLocation.ApplicationDatabase; string fileFullName = "Documents/Public/PLP_Lookups/JobCodeLookup.csv"; bool includeContentFileBytes = true; bool failGracefully = true; XFFileEx sourceFile = BRApi.FileSystem.GetFile(si, location, fileFullName, includeContentFileBytes, failGracefully); if (sourceFile == null || sourceFile.XFFile == null || sourceFile.XFFile.ContentFileBytes == null) { throw new XFException(si, new Exception($"Source file '{fileFullName}' could not be loaded or is empty.")); } // Convert byte[] to string using UTF8 string textContent = System.Text.Encoding.UTF8.GetString(sourceFile.XFFile.ContentFileBytes); // Split into lines string[] lines = textContent.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); // Detect delimiter from the first line char delimiter = ','; if (lines.Length > 0) { string firstLine = lines[0]; if (firstLine.Contains("\t")) delimiter = '\t'; else if (firstLine.Contains(";")) delimiter = ';'; else if (firstLine.Contains("|")) delimiter = '|'; // Default stays as comma } // Parse file into dictionary: JobCode -> JobCodeDesc Dictionary<string, string=""> jobCodeLookup = new Dictionary<string, string="">(StringComparer.OrdinalIgnoreCase); foreach (string line in lines) { string[] parts = line.Split(delimiter); if (parts.Length >= 2) { string code = parts[0].Trim(); string desc = parts[1].Trim(); if (!jobCodeLookup.ContainsKey(code)) { jobCodeLookup[code] = desc; } } } foreach (var row in tableView.Rows) { //identify rows to skip if (row.IsHeader) continue; var originalStatus = row.Items["Status"].Value?.ToString(); if (string.IsNullOrWhiteSpace(originalStatus)) continue; if (!row.Items["JobCode"].IsDirty()) continue; string jcName = row.Items["JobCode"].Value?.ToString(); string empId = row.Items["EmployeeID"].Value?.ToString(); if (jobCodeLookup.TryGetValue(jcName, out var jcDescription)) { row.Items["JobCodeDescription"].Value = jcDescription; } else { invalidJobCodes.Add($"EmployeeID {empId}, JobCode {jcName}"); row.Items["JobCodeDescription"].Value = null; } } if (invalidJobCodes.Count > 0) { string errorMessage = "Invalid job codes detected:" + Environment.NewLine + string.Join(Environment.NewLine, invalidJobCodes); throw new XFException(si, new Exception(errorMessage)); } }</string,></string,></string></string> File Explorer Part 1jzhang3 hours agoOneStream Employee13Views0likes0CommentsUnsaved changes lost despite clicking Cancel when navigating between Input Forms?
Hi all, If I enter data in an Input Form without saving and then navigate to another Input Form workflow step, the "The selected item has not been saved" warning message is displayed. However, Cancel does not prevent navigation and the unsaved changes are lost. I've tested several other navigation scenarios (changing period, scenario, entity, navigating to dashboards, cube views, or non-Input Form workflow steps) and in those cases Cancel behaves as expected and preserves the unsaved data. The issue seems to occur only when moving from one Input Form workflow step to another. Any ideas on how to prevent unsaved changes from being lost if a user forgets to click Save before leaving the Input Form?4Views0likes0CommentsButtons: Does not aling when using browser.
Hi If/when we are going to move to the browser solution, I would like to have my dashboard menu to be align to left. This is how it looks in the app: This is how it looks in browser. It is OK that icons are in colors, but I can't align the text to left. Component properties are the following (with no effect) Any suggestion on how to align it? Regards OleOle_S_P8 hours agoNew Contributor III8Views0likes0CommentsRun a DM as a different user
Hi there, We have one Business Rule that reorganize some security groups adding/removing Parent Groups based on a certain hierarchy, however, we are facing the issue that when the user executing this Business Rule belongs to a group that is being reorganized, we get the following error message: "Security Access Error. You cannot add/remove yourself or a group that you belong to or an Administrators group to/from the current group." That error is perfectly reasonable, but we need to find a way to bypass that. In other softwares exists the possibility to execute a Job as a different user (usually non-interactive) which has the required security configuration to ensure the process is executed successfully. How can we achive that same result in OneStream? Thank you! Bests,Solvedogonzalez18 hours agoNew Contributor II137Views0likes4CommentsExcel Addin - Calculate
Hi, I am using OneStream version 8.2 and the Excel Add-In with a workbook that contains XFGetCell formulas. The workbook retrieves data successfully, and Refresh Workbook works as expected. However, the Calculate, Translate, and Consolidate buttons in the OneStream ribbon are disabled (grayed out). I am logged in successfully and can retrieve data through XFGetCell formulas, but I cannot perform any processing actions from Excel. Could anyone help me understand: What conditions must be met in OneStream 8.2 for the Calculate, Translate, and Consolidate buttons to become enabled? Is there any way to trigger Calculate, Translate, or Consolidate from Excel when working with XFGetCell-based templates? Thank you!Manju20 hours agoNew Contributor II31Views0likes1CommentList of User Default Home Pages
Hi Folks, Wondering if anyone has built a BR or query to compile a list of Users and their Default Home Page. I know its in the UserAppSettings.xml File within File Explorer under Internal/User, and you can set individuals through the Admin Solution Tools, however I have not found a good way to See what is already set without going to each user individually (that would not be very practical). Appreciate any help! Stephaniesmarshall221 hours agoNew Contributor II23Views0likes1CommentEnvironment Application Count Dashboard
Our users are wanting to know how many applications are in each environment, then show the applications under each environment by clicking on the environment, plus the ability to enter a comment next to the application. Similar to the Cloud Admin Tool, Applications on top, user would click the environment, the grid would then show the applications. A text field next to the application name where they could input a comment. Any thoughts on how this could be done? Appreciate it in advance!27Views1like1CommentIssue in Web Content and File Viewer component to directly open a HTML file in a browser
Dear community, I currently have an html document which is located in the file Explorer under "Documents/Public" folder. I am trying to get this HTML document to be presented into the components, embedded in a dashboard. However, with either a Web Content component or a File Viewer component (which will pinpoint to this specific file in Application Database File, as soon as I open the dashboard, it will load the html page into my default browser... I am using OS v8.1 ... is it a known bug or the expected behaviour ? What is even more strange, directing the Full File Name to a URL will correctly open a document in a dashboard ... Regards,3.3KViews0likes14CommentsCourse Announcement: Workforce Planning with Line Item Modeling
1 MIN READ Course Description: This course covers a complete, end‑to‑end introduction to Workforce Planning within the Line Item Modeling (LIM) solution. You will explore how to install and configure the solution, define and manage the Register, load and govern workforce data, build and use global/cube/lookup drivers, create formulas, manage filter groups, construct and calculate plans, apply security settings, and process results for reporting and dashboard analysis. Through guided examples and use cases, the course enables you to model, maintain, and analyze workforce plans. Delivery Types: On-Demand (OD) Duration: 8 hours Availability: This course is fee based/for purchase a la carte. This course is available via Passport Access. Course Link: Workforce Planning with LIMagoralewski1 day agoCommunity Manager25Views0likes0Comments
Getting Started
Learn more about the OneStream Community with the links below.