Создание пользовательского экспорта в Excel для ReportViewer (rdlc)

Я заинтересован в создании настраиваемой опции экспорта в Excel для моего отчета в ReportViewer. Это в основном потому, что я хочу отключить pdf, и я сделал это с помощью:

 ReportViewer1.ShowExportControls = false;

Так как в ReportViewer нет возможности отключить какую-либо конкретную функцию экспорта (например, pdf, но не excel). Вот мой (слегка) модифицированный код ниже. В идеале мне бы хотелось что-то похожее на предыдущие параметры экспорта, где я могу сохранить файл в любое место, которое я хочу.

РЕДАКТИРОВАТЬ: Псевдослучайный образец должен быть сгенерирован. Существует несколько способов / или алгоритмов для создания различного контента. Все алгоритмы будут генерировать список символов (но это может быть что угодно ...

Установка:
Псевдослучайный образец должен быть сгенерирован. Существует несколько способов / или алгоритмов для создания различного контента. Все алгоритмы будут генерировать список символов (но может быть и любым другим) ... важная часть заключается в том, что все они возвращают одинаковые типы значений и нуждаются в одинаковых типах входных аргументов.

Это должно быть можно вызвать метод GetRandomPattern (), который будет использовать случайный один из алгоритмов при каждом его вызове.

Мой первый подход состоял в том, чтобы поместить каждый алгоритм в его собственную функцию и выбирать случайный из них каждый раз, когда GetRandompattern () называется. Но я не придумал другого способа выбора между ними, кроме заявления о переключении, которое было бы неудобным, безобразным и негибким.

class PatternGenerator{
 public:
  list<char> GetRandomPattern();
 private:
  list<char>GeneratePatternA(foo bar);
  list<char>GeneratePatternB(foo bar);
  ........
  list<char>GeneratePatternX(foo bar);
}

Как можно было бы выбрать случайную функцию GeneratePattern при каждом вызове метода GetRandomPattern () ?

Или весь класс должен быть оформлен по-другому?

Большое спасибо

6
задан zitroneneis 16 August 2010 в 17:36
поделиться

4 ответа

Спасибо за ваш большой вклад. Я решил использовать указатели на функции, главным образом потому, что я не знал их раньше, и они кажутся очень мощными, и это был хороший шанс познакомиться с ними, но также потому, что это экономит мне много строк кода.

Если бы я использовал Ruby / Java / C #, я бы выбрал предложенный шаблон проектирования стратегии; -)

class PatternGenerator{
 typedef list<char>(PatternGenerator::*createPatternFunctionPtr);
public:
 PatternGenerator(){
  Initialize();
   }
 GetRandomPattern(){
  int randomMethod = (rand()%functionPointerVector.size());
  createPatternFunctionPtr randomFunction = functionPointerVector.at( randomMethod );
  list<char> pattern = (this->*randomFunction)();
  return pattern;
  }
private:
  void Initialize(){
   createPatternFunctionPtr methodA = &PatternGenerator::GeneratePatternA;
   createPatternFunctionPtr methodB = &PatternGenerator::GeneratePatternB;
   ...
   functionPointerVector.push_back( methodA );
   functionPointerVector.push_back( methodB );
   }
  list<char>GeneratePatternA(){
   ...}
  list<char>GeneratePatternB(){
   ...}
  vector< createPattern > functionPointerVector;

Читаемость не намного хуже, чем была бы с решением шаблона проектирования, это просто чтобы добавить новые алгоритмы, арифметика указателей заключена в класс, это предотвращает утечки памяти, и это очень быстро и эффективно ...

1
ответ дан 8 December 2019 в 14:38
поделиться

Создайте один класс для каждого алгоритма, каждый из которых подклассифицирует класс генератора. Поместите экземпляры этих объектов в список. Выберите один случайным образом и используйте его!

В более общем случае, если вы начинаете создавать несколько альтернативных методов с одинаковой сигнатурой, что-то кричит вам "поместите нас в классы-братья" :)

Update Не могу удержаться от того, чтобы еще немного поспорить за объектно-ориентированное решение после того, как пришло предложение с указателями

  • Представьте, что в какой-то момент вы хотите вывести, какой метод создал какую случайную вещь. С объектами это легко, просто добавьте метод "name" или что-то в этом роде. Как вы хотите добиться этого, если все, что у вас есть - это указатель? (Ага, создать словарь из указателей на строки, хм...)
  • Представьте, что вы обнаружили, что у вас есть десять методов, пять из которых отличаются только параметром. И вы пишете пять функций "только для того, чтобы очистить код от ООП-мусора"? Или вы предпочитаете иметь функцию, которая может хранить некоторое состояние (также известное как объект?)
  • Я пытаюсь сказать, что это хрестоматийное применение для некоторых конструкций ООП. Вышеприведенные пункты просто пытаются немного дополнить это и доказать, что даже если сейчас это работает с указателями, это не является перспективным решением. И вы не должны бояться создавать код, который говорит с читателем (т.е. с вашим будущим вами, через четыре недели или около того), рассказывая ему, что он делает
9
ответ дан 8 December 2019 в 14:38
поделиться

Вы можете создать массив указателей функций. Это избавляет от необходимости создавать целую кучу различных классов, хотя вам все равно придется назначать указатели функций элементам массива. В любом случае, если вы сделаете это, будет много повторяющихся строк. В вашем примере они находятся в методе GetRandomPattern. В моем - в конструкторе PatternGenerator.

#define FUNCTION_COUNT 24
typedef list<char>(*generatorFunc)(foo);

class PatternGenerator{
    public:
        PatternGenerator() {
            functions[0] = &GeneratePatternA;
            functions[1] = &GeneratePatternB;
            ...
            functions[24] = &GeneratePatternX;
        }
        list<char> GetRandomPattern() {
            foo bar = value;
            int funcToUse = rand()%FUNCTION_COUNT;
            functions[funcToUse](bar);
        }
    private:
        generatorFunc functions[FUNCTION_COUNT];
}
5
ответ дан 8 December 2019 в 14:38
поделиться

Одним из способов избежать переключаемого кодирования является использование шаблона разработки стратегии. Например:

class IRandomPatternGenerator
{
public:
  virtual list<int> makePattern(foo bar);
};

class ARandomPatternGenerator : public IRandomPatternGenerator
{
public:
  virtual list<int> makePattern(foo bar)
  {
    ...    
  }
};

class BRandomPatternGenerator : public IRandomPatternGenerator
{
public:
  virtual list<int> makePattern(foo bar)
  {
    ...    
  }
};

Затем вы можете выбрать конкретный алгоритм в зависимости от типа времени выполнения вашего экземпляра RandomPatternGenerator. (В качестве примера предлагается создание списка наподобие nicolas78)

1
ответ дан 8 December 2019 в 14:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: