diff --git a/instat/dlgName.vb b/instat/dlgName.vb index 0be8141d4a..aa20aad2e6 100644 --- a/instat/dlgName.vb +++ b/instat/dlgName.vb @@ -34,6 +34,7 @@ Public Class dlgName Private clsStartwithFunction, clsRegexFunction, clsEndswithFunction, clsMatchesFunction, clsContainsFunction As New RFunction Private WithEvents grdCurrentWorkSheet As Worksheet Private dctRowsNewNameChanged As New Dictionary(Of Integer, String) + Private dctRowsCurrentName As New Dictionary(Of Integer, String) Private dctRowsNewLabelChanged As New Dictionary(Of Integer, String) Private dctNameRowsValues As New Dictionary(Of Integer, String) Private dctCaseOptions As New Dictionary(Of String, String) @@ -99,7 +100,7 @@ Public Class dlgName ucrPnlCase.AddRadioButton(rdoAbbreviate, "abbreviate") ucrPnlCase.AddRadioButton(rdoReplace, "stringr::str_replace") - ucrPnlSelectData.SetParameter(New RParameter("data", 0)) + ucrPnlSelectData.AddRadioButton(rdoWholeDataFrame) ucrPnlSelectData.AddRadioButton(rdoSelectedColumn) ucrPnlSelectData.AddParameterValuesCondition(rdoWholeDataFrame, "checked", "whole") @@ -189,6 +190,7 @@ Public Class dlgName ucrSelectVariables.Reset() dctRowsNewNameChanged.Clear() dctRowsNewLabelChanged.Clear() + dctRowsCurrentName.Clear() bCurrentCell = False clsNewColNameDataframeFunction.SetRCommand("data.frame") @@ -353,10 +355,14 @@ Public Class dlgName If e.Range.Rows > 1 Then For iRow As Integer = iStartRowIndex To grdCurrentWorkSheet.SelectionRange.EndRow Dim strNewData As String = ValidateRVariable(grdCurrentWorkSheet.GetCellData(row:=iRow, col:=iColIndex), iColIndex) + Dim strOldData As String = grdCurrentWorkSheet.GetCellData(row:=iRow, col:=0) + GetOldNames(iRow, strOldData) RenameColumns(strNewData, iRow, iColIndex) Next Else Dim strNewData As String = ValidateRVariable(grdCurrentWorkSheet.GetCellData(row:=e.Range.Row, col:=iColIndex), iColIndex) + Dim strOldData As String = grdCurrentWorkSheet.GetCellData(row:=e.Range.Row, col:=0) + GetOldNames(e.Range.Row, strOldData) RenameColumns(strNewData, iStartRowIndex, iColIndex) End If ValidateNamesFromDictionary(iColIndex) @@ -406,10 +412,22 @@ Public Class dlgName Private Sub grdCurrSheet_AfterCellEdit(sender As Object, e As CellAfterEditEventArgs) Handles grdCurrentWorkSheet.AfterCellEdit Dim iCol As Integer = e.Cell.Column Dim strNewData As String = ValidateRVariable(e.NewData, iCol) + + Dim strFirstColumnData As String = grdCurrentWorkSheet(e.Cell.Row, 0).ToString() + + GetOldNames(e.Cell.Row, strFirstColumnData) RenameColumns(strNewData, e.Cell.Row, iCol) ValidateNamesFromDictionary(iCol) End Sub + Private Sub GetOldNames(iRow As Integer, strOldName As String) + If Not dctRowsCurrentName.ContainsKey(iRow) Then + dctRowsCurrentName.Add(iRow, strOldName) + Else + dctRowsCurrentName(iRow) = strOldName + End If + End Sub + Private Sub GetVariables(strNewData As String, iRowIndex As Integer, iColIndex As Integer) If rdoMultiple.Checked Then If iColIndex = 1 Then @@ -417,7 +435,7 @@ Public Class dlgName AddChangedNewNameRows(iRowIndex, strNewData) clsNewColNameDataframeFunction.AddParameter("cols", GetValuesAsVector(dctRowsNewNameChanged), iPosition:=0) - clsNewColNameDataframeFunction.AddParameter("index", "c(" & String.Join(",", dctRowsNewNameChanged.Keys.ToArray) & ")", iPosition:=1) + clsNewColNameDataframeFunction.AddParameter("old_names", GetValuesAsVector(dctRowsCurrentName), iPosition:=1) clsDefaultRFunction.AddParameter("new_column_names_df", clsRFunctionParameter:=clsNewColNameDataframeFunction, iPosition:=8) Else clsNewColNameDataframeFunction.RemoveParameterByName("cols") @@ -602,7 +620,9 @@ Public Class dlgName rdoReplace.Visible = rdoWholeDataFrame.Checked If rdoWholeDataFrame.Checked Then ucrReceiverColumns.Visible = False + clsDummyFunction.AddParameter("checked", "whole", iPosition:=1) Else + clsDummyFunction.AddParameter("checked", "selected", iPosition:=1) ucrReceiverColumns.SetMeAsReceiver() If rdoReplace.Checked Then rdoMakeCleanNames.Checked = True @@ -681,6 +701,8 @@ Public Class dlgName Dim parsedValue As Boolean Dim strNewData As String = ValidateRVariable(e.Text, iCol) If Not strNewData.ToLower.Equals("t") AndAlso Not strNewData.ToLower.Equals("f") AndAlso Not IsNumeric(strNewData) AndAlso Not Boolean.TryParse(strNewData, parsedValue) Then + Dim strFirstColumnData As String = grdCurrentWorkSheet(e.Cell.Row, 0).ToString() + GetOldNames(e.Cell.Row, strFirstColumnData) RenameColumns(strNewData, e.Cell.Row, iCol) ValidateNamesFromDictionary(iCol) End If @@ -713,6 +735,7 @@ Public Class dlgName clsDefaultRFunction.AddParameter(".cols", clsRFunctionParameter:=clsContainsFunction, iPosition:=3) clsDefaultRFunction.AddParameter(".fn", "stringr::str_replace_all", iPosition:=2) End Select + Else clsDefaultRFunction.RemoveParameterByName("replacement") clsDefaultRFunction.RemoveParameterByName(".cols") diff --git a/instat/dlgSelect.vb b/instat/dlgSelect.vb index 2bc3630c75..9d9d2acc09 100644 --- a/instat/dlgSelect.vb +++ b/instat/dlgSelect.vb @@ -137,6 +137,12 @@ Public Class dlgSelect End Sub Private Sub cmdDefineNewSelect_Click(sender As Object, e As EventArgs) Handles cmdDefineNewSelect.Click + If frmMain.IsColumnSelectionApplied Then + Dim clsRemoveCurrentSelection As New RFunction + clsRemoveCurrentSelection.SetRCommand(frmMain.clsRLink.strInstatDataObject & "$remove_current_column_selection") + clsRemoveCurrentSelection.AddParameter("data_name", Chr(34) & ucrSelectorForSelectColumns.strCurrentDataFrame & Chr(34)) + frmMain.clsRLink.RunScript(clsRemoveCurrentSelection.ToScript, strComment:="Remove current selection") + End If dlgSelectColumns.SetDefaultDataFrame(ucrSelectorForSelectColumns.ucrAvailableDataFrames.strCurrDataFrame) dlgSelectColumns.ShowDialog() ucrSelectorForSelectColumns.LoadList() diff --git a/instat/frmMain.vb b/instat/frmMain.vb index 0cd1865bd1..abd0665291 100644 --- a/instat/frmMain.vb +++ b/instat/frmMain.vb @@ -1747,6 +1747,10 @@ Public Class frmMain ucrDataViewer.UseColumnSelectionInDataView(bUseColumnSelecion) End Sub + Public Function IsColumnSelectionApplied() As Boolean + Return ucrDataViewer.IsColumnSelectionApplied + End Function + Public Sub SetCurrentDataFrame(strDataName As String) ucrDataViewer.SetCurrentDataFrame(strDataName) ucrColumnMeta.SetCurrentDataFrame(strDataName) diff --git a/instat/static/InstatObject/R/data_object_R6.R b/instat/static/InstatObject/R/data_object_R6.R index b123c0a54e..4183798f63 100644 --- a/instat/static/InstatObject/R/data_object_R6.R +++ b/instat/static/InstatObject/R/data_object_R6.R @@ -921,6 +921,36 @@ DataSheet$set("public", "cor", function(x_col_names, y_col_name, use = "everythi } ) +DataSheet$set("public", "update_selection", function(new_values, column_selection_name = NULL) { + if (missing(new_values)) stop("new_values is required") + if (missing(column_selection_name)) stop("column_selection_name is required") + + column_selection_obj <- private$column_selections[[column_selection_name]] + + if (is.null(column_selection_obj)) { + stop("No column selection found with the name: ", column_selection_name) + } + + # Update conditions in the column selection with new values + updated_conditions <- lapply(column_selection_obj$conditions, function(condition) { + # Check if the parameters exist and replace them with new values + if ("parameters" %in% names(condition)) { + condition$parameters$x <- new_values + } + return(condition) + }) + + # Update the column selection object with the new conditions + column_selection_obj$conditions <- updated_conditions + private$column_selections[[column_selection_name]] <- column_selection_obj + + # Optionally, mark data as changed + self$data_changed <- TRUE + + message("Column selection '", column_selection_name, "' updated successfully with new values.") +}) + + DataSheet$set("public", "rename_column_in_data", function(curr_col_name = "", new_col_name = "", label = "", type = "single", .fn, .cols = everything(), new_column_names_df, new_labels_df, ...) { curr_data <- self$get_data_frame(use_current_filter = FALSE, use_column_selection = FALSE) @@ -954,8 +984,18 @@ DataSheet$set("public", "rename_column_in_data", function(curr_col_name = "", ne purrr::map(.x = keys_to_delete, .f = ~self$remove_key(key_name = names(active_keys[.x]))) } } - if(self$column_selection_applied()) self$remove_current_column_selection() # Need to use private$data here because changing names of data field + names(private$data)[names(curr_data) == curr_col_name] <- new_col_name + + column_names <- self$get_column_names() + + if (anyNA(column_names)) { + column_names[is.na(column_names)] <- new_col_name + } else { + column_names <- new_col_name + } + + self$update_selection(column_names, private$.current_column_selection$name) if(any(c("sfc", "sfc_MULTIPOLYGON") %in% class(private$data[[curr_col_name]]))){ # Update the geometry column reference sf::st_geometry(private$data) <- new_col_name @@ -976,11 +1016,22 @@ DataSheet$set("public", "rename_column_in_data", function(curr_col_name = "", ne } else if (type == "multiple") { if (!missing(new_column_names_df)) { new_col_names <- new_column_names_df[, 1] - cols_changed_index <- new_column_names_df[, 2] + cols_changed_index <- which(names(private$data) %in% new_column_names_df[, 2]) curr_col_names <- names(private$data) curr_col_names[cols_changed_index] <- new_col_names if(any(duplicated(curr_col_names))) stop("Cannot rename columns. Column names must be unique.") - if(self$column_selection_applied()) self$remove_current_column_selection() + names(private$data)[cols_changed_index] <- new_col_names + + column_names <- self$get_column_names() + + if (anyNA(column_names)) { + column_names[is.na(column_names)] <- new_col_names + } else { + column_names <- new_col_names + } + + self$update_selection(column_names, private$.current_column_selection$name) + if(any(c("sfc", "sfc_MULTIPOLYGON") %in% class(private$dataprivate$data)[cols_changed_index])){ # Update the geometry column reference sf::st_geometry(private$data) <- new_col_names @@ -1005,19 +1056,29 @@ DataSheet$set("public", "rename_column_in_data", function(curr_col_name = "", ne } else if (type == "rename_with") { if (missing(.fn)) stop(.fn, "is missing with no default.") curr_col_names <- names(curr_data) + column_names <- self$get_column_names() private$data <- curr_data |> dplyr::rename_with( .fn = .fn, .cols = {{ .cols }}, ... ) - if(self$column_selection_applied()) self$remove_current_column_selection() new_col_names <- names(private$data) if (!all(new_col_names %in% curr_col_names)) { new_col_names <- new_col_names[!(new_col_names %in% curr_col_names)] for (i in seq_along(new_col_names)) { self$append_to_variables_metadata(new_col_names[i], name_label, new_col_names[i]) } + + column_names <- self$get_column_names() + if (anyNA(column_names)) { + column_names[is.na(column_names)] <- new_col_names + } else { + column_names <- new_col_names + } + + self$update_selection(column_names, private$.current_column_selection$name) + self$data_changed <- TRUE self$variables_metadata_changed <- TRUE } diff --git a/instat/ucrDataView.vb b/instat/ucrDataView.vb index 54ad461bc8..ff9b849a50 100644 --- a/instat/ucrDataView.vb +++ b/instat/ucrDataView.vb @@ -466,6 +466,10 @@ Public Class ucrDataView End If End Sub + Public Function IsColumnSelectionApplied() As Boolean + Return GetCurrentDataFrameFocus().clsFilterOrColumnSelection.bColumnSelectionApplied + End Function + Private Function GetSelectedColumns() As List(Of clsColumnHeaderDisplay) Return _grid.GetSelectedColumns() End Function