Применение условного форматирования на основе правила (пример 4)

Требования к операционной системе: iOS 5.0 и выше.

Мобильное устройство: iPad.

Описание

В данном примере описывается настройка условного форматирования для ячеек таблицы на основе правила «Значение между A и B». Для применения свойств правила применяется пул настроек условного форматирования.

Исходный код

Для выполнения примера необходимо разместить взамен метода executeExample класса ViewController (см. раздел «Отображение экспресс-отчёта») следующий код:

-(void)executeExample {
    MAExpressAnalysisReportViewController *contr = (MAExpressAnalysisReportViewController *)m_controller;
    // Получаем массив контроллеров представлений данных
    NSArray *controllers =[contr dataViewControllers];
    // Определяем значения A и B
    double valueA = 7000;
    double valueB = 8000;
    
    // Перебираем в цикле контроллеры представлений данных
    for(NSObject *controller in controllers)
    {
        // Проверяем, является ли текущий контроллер контроллером представления данных в виде таблицы
        if([controller isMemberOfClass:[MAGridDataViewController class]])
        {
            // Получаем объект контроллера представления данных в виде таблицы
            MAGridDataViewController *gridController = (MAGridDataViewController *)controller;
            // Получаем представление контроллера
            UIView *view = [gridController view];
            // Получаем массив вложенных представлений
            NSArray *subviews = [view subviews];
            // Перебираем в цикле вложенные представления
            for(NSObject *subview in subviews)
            {
                // Проверяем, является ли текущее представление табличным представлением
                if([subview isMemberOfClass:[NuGridView class]])
                {
                    // Получаем объект табличного представления
                    NuGridView *gridView = (NuGridView *)subview;
                    // Получаем делегат для работы с таблицей
                    MAGridDelegate *delegate = (MAGridDelegate*)[gridView gridDelegate];
                    // Получаем прокси-источник данных
                    MAGridProxyDataSource *proxyDatasource = (MAGridProxyDataSource*)[delegate proxyDataSource];
                    
                    // Определяем настройки условного форматирования на базе правил
                    MAConditionalFormattingRules *rules = [[MAConditionalFormattingRules new] autorelease];
                    // Правила будем применять для всей таблицы
                    [rules setArea: kCFAEntireTable];
                    
                    // Получаем правило условного форматирования
                    MAConditionalFormattingRule *formattingRule = [rules ruleByType: kCFRTBetween];
                    // Помечаем созданное правило как активное
                    [formattingRule setActive: YES];
                    // Устанавливаем цвет заливки для ячеек, удовлетворяющих правилу
                    [formattingRule setColor: [UIColor colorWithRed:1 green:0.77 blue:0.27 alpha:1]];
                    // Используем абсолютные числовые значения
                    [formattingRule setValueFormat: kCFRVFNumber];
                    // Разрешаем использовать сортировку данных
                    [formattingRule setApplyOrder: YES];
                    
                    // Создаём пул настроек условного форматирования
                    MAConditionalFormattingPool *formattingPool = [[MAConditionalFormattingPool new] autorelease];
                    // Устанавливаем пул для правила условного форматирования
                    [formattingRule setConditionalFormattingPool: formattingPool];
                    
                    // Инициализируем объект с предопределёнными данными
                    MAConditionalFormattingRulePreparedData *preparedData = [[MAConditionalFormattingRulePreparedData new] autorelease];
                    NSMutableArray *dataArray = nil; // Массив данных
                    double total = 0.0; // Общая сумма значений данных
                    
                    // Проверяем, требуется ли подготовка настроек для правила условного форматирования
                    bool isNeedPrepareData = [formattingRule needPrepareDataForCellInRow:nil andColumn:nil withArea:[rules area]];
                    if (isNeedPrepareData) {
                        // Подготавливаем данные
                        [preparedData setPreparedValueA: [NSNumber numberWithDouble: valueA]];
                        [preparedData setPreparedValueB: [NSNumber numberWithDouble: valueB]];
                        // Записываем подготовленные данные в пул настроек условного форматирования
                        [formattingPool putPreparedData: preparedData forRuleInRow:nil andColumn:nil withType: [formattingRule type] withArea:kCFAEntireTable];
                        
                        // Создаём отсортированный массив данных для всей таблицы
                        dataArray = [self dataArrayForEntireTableForDataSource: proxyDatasource];
                        [dataArray removeObjectIdenticalTo:[NSNull null]];
                        [dataArray sortUsingSelector:@selector(compare:)];
                        // Вычисляем общую сумму данных массива
                        total = [self calculateDataTotal:dataArray];
                        
                        if ([formattingRule applyOrder]) {
                            // Подготавливаем данные для правила условного форматирования
                            [formattingRule prepareWithSortedDataArray:dataArray
                            andDataTotal:total
                            inRow:nil
                            andColumn:nil
                            withArea: [rules area]];
                        }
                    }
                    // Создаём помощника для работы с настройками условного форматирования
                    MAConditionalFormattingHelper *formattingHelper = [[MAConditionalFormattingHelper alloc] initWithProxyDataSource: proxyDatasource];
                    // Применяем настройки условного форматирования для всей таблицы
                    [formattingHelper applyGlobalConditionalFormat: rules];
                    
                    // Получаем среднее значение в интервале (A; B)
                    double valueA = [[preparedData preparedValueA] doubleValue];
                    double valueB = [[preparedData preparedValueB] doubleValue];
                    double averageValue = (valueA + valueB) / 2;
                    // Определяем, принадлежит ли полученное значение данному интервалу
                    bool conformsToValue = [formattingRule conformsToValue: [NSNumber numberWithDouble: averageValue]];
                    NSLog(@"Значение %f %@принадлежит интервалу (%f; %f)", averageValue, (conformsToValue? @"": @"не "),
                    valueA, valueB);
                    // Определяем цвет, соответствующий данному интервалу
                    UIColor *color = [rules colorForValue: [NSNumber numberWithDouble: averageValue]];
                    const CGFloat *components = CGColorGetComponents([color CGColor]);
                    if (components != NULL) {
                        CGFloat r = components[0];
                        CGFloat g = components[1];
                        CGFloat b = components[2];
                        NSString *hexString=[NSString stringWithFormat:@"%02X%02X%02X", (int)(r * 255), (int)(g * 255), (int)(b * 255)];
                        NSLog(@"Цвет, соответствующий значению %f: #%@", averageValue, hexString);
                    }
                }
            }
        }
    }
}
// Создаёт массив данных для всей таблицы
- (NSMutableArray *)dataArrayForEntireTableForDataSource:(MAGridProxyDataSource *)dataSource {
    // Получаем объект, предназначенный для работы с таблицей
    SPPLPivotTable pivotTable = dataSource.dataSource.pivotTable;
    // Получаем количество строк
    int rowCount = pivotTable->leftHeader()->elements()->elementsCount();
    // Получаем количество столбцов
    int columnCount = pivotTable->topHeader()->elements()->elementsCount();
    // Создаём массив данных
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:rowCount * columnCount];
    for (int r = 0; r < rowCount; ++r) {
        SPPLPivotTableHeaderElement leftElement = pivotTable->leftHeader()->elements()->getElementByIndex(r);
        BOOL isRowInTotal = pivotTable->leftHeader()->elements()->isElementInTotals(leftElement);
        if (isRowInTotal) {
            continue;
        }
        for (int c = 0; c < columnCount; ++c) {
            SPPLPivotTableHeaderElement topElement = pivotTable->topHeader()->elements()->getElementByIndex(c);
            BOOL isColumnInTotal = pivotTable->topHeader()->elements()->isElementInTotals(topElement);
            if (isColumnInTotal) {
                continue;
            }
            // Получаем данные ячейки таблицы
            SNID data = pivotTable->getData(r, c);
            NSObject *value = (data != NULL) ? (NSObject *)data->nsObject() : nil;
            if ([value isKindOfClass:NSNumber.class]) {
                // Добавляем значение ячейки в массив
                [result addObject:value];
            }
        }
    }
    
    return result;
}
// Вычисляет сумму значений данных из указанного массива
- (double)calculateDataTotal:(NSArray *)dataArray {
    double total = 0.0; // Сумма значений всех данных
    for (NSNumber *number in dataArray) {
        if (![number isEqual:nil]) {
            double doubleValue = [number doubleValue];
            total += doubleValue;
        }
    }
    return total;
}

В результате выполнения примера для всей таблицы экспресс-отчёта было применено условное форматирование с использованием правила «Ячейки между A и B». Так все ячейки, содержащие значения от 7000 до 8000, были окрашены в жёлтый цвет:

В консоли среды разработки были выведены уведомления, принадлежит ли значение 7500 интервалу (7000; 8000), а также цвет заливки ячейки, соответствующий данному значению:

Значение 7500.000000 принадлежит интервалу (7000.000000; 8000.000000)

Цвет, соответствующий значению 7500.000000: #FFC444

Аналогичный результат получим, если заменим фрагмента кода

[formattingRule prepareWithSortedDataArray:dataArray
andDataTotal:total
inRow:nil
andColumn:nil
withArea: [rules area]];

на следующий сценарий:

MAConditionalFormattingRulePreparedData *data =
[formattingPool preparedDataForRuleInRow:nil andColumn:nil
withType:[formattingRule type] withArea: [rules area]];
[formattingRule setValue:data forKey:@"preparedData"];
[formattingRule setValue:[NSNumber numberWithBool: NO]
forKey:@"empty"];

После выполнения примера условное форматирование будет применено с теми же настройками.

См. также:

Примеры использования компонентов